public static boolean isAllowed(Connection connection) { if (!allowedIPs.isEmpty()) { // The server is using a whitelist so check that the IP address of the client // is authorized to connect to the server boolean forbidAccess = false; try { if (!allowedIPs.containsKey(connection.getHostAddress())) { byte[] address = connection.getAddress(); String range1 = (address[0] & 0xff) + "." + (address[1] & 0xff) + "." + (address[2] & 0xff) + ".*"; String range2 = (address[0] & 0xff) + "." + (address[1] & 0xff) + ".*.*"; String range3 = (address[0] & 0xff) + ".*.*.*"; if (!allowedIPs.containsKey(range1) && !allowedIPs.containsKey(range2) && !allowedIPs.containsKey(range3)) { forbidAccess = true; } } } catch (UnknownHostException e) { forbidAccess = true; } return !forbidAccess; } return true; }
/** * Creates a new client session that was established to the specified connection manager. The new * session will not be findable through its stream ID. * * @param connectionManagerDomain the connection manager that is handling the connection of the * session. * @param streamID the stream ID created by the connection manager for the new session. * @param hostName the address's hostname of the client or null if using old connection manager. * @param hostAddress the textual representation of the address of the client or null if using old * CM. * @return true if a session was created or false if the client should disconnect. */ public boolean createClientSession( String connectionManagerDomain, String streamID, String hostName, String hostAddress) { Connection connection = new ClientSessionConnection(connectionManagerDomain, hostName, hostAddress); // Check if client is allowed to connect from the specified IP address. Ignore the checking if // connection // manager is old version and is not passing client's address byte[] address = null; try { address = connection.getAddress(); } catch (UnknownHostException e) { // Ignore } if (address == null || LocalClientSession.isAllowed(connection)) { LocalClientSession session = SessionManager.getInstance().createClientSession(connection, new BasicStreamID(streamID)); // Register that this streamID belongs to the specified connection manager streamIDs.put(streamID, connectionManagerDomain); // Register which sessions are being hosted by the speicifed connection manager Map<String, LocalClientSession> sessions = sessionsByManager.get(connectionManagerDomain); if (sessions == null) { synchronized (connectionManagerDomain.intern()) { sessions = sessionsByManager.get(connectionManagerDomain); if (sessions == null) { sessions = new ConcurrentHashMap<>(); sessionsByManager.put(connectionManagerDomain, sessions); } } } sessions.put(streamID, session); return true; } return false; }
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; } }
/** * Returns a newly created session between the server and a client. The session will be created * and returned only if correct name/prefix (i.e. 'stream' or 'flash') and namespace were provided * by the client. * * @param serverName the name of the server where the session is connecting to. * @param xpp the parser that is reading the provided XML through the connection. * @param connection the connection with the client. * @return a newly created session between the server and a client. * @throws org.xmlpull.v1.XmlPullParserException if an error occurs while parsing incoming data. */ public static LocalClientSession createSession( String serverName, XmlPullParser xpp, Connection connection) throws XmlPullParserException { boolean isFlashClient = xpp.getPrefix().equals("flash"); connection.setFlashClient(isFlashClient); // Conduct error checking, the opening tag should be 'stream' // in the 'etherx' namespace if (!xpp.getName().equals("stream") && !isFlashClient) { throw new XmlPullParserException(LocaleUtils.getLocalizedString("admin.error.bad-stream")); } if (!xpp.getNamespace(xpp.getPrefix()).equals(ETHERX_NAMESPACE) && !(isFlashClient && xpp.getNamespace(xpp.getPrefix()).equals(FLASH_NAMESPACE))) { throw new XmlPullParserException(LocaleUtils.getLocalizedString("admin.error.bad-namespace")); } if (!allowedIPs.isEmpty()) { String hostAddress = "Unknown"; // The server is using a whitelist so check that the IP address of the client // is authorized to connect to the server try { hostAddress = connection.getHostAddress(); } catch (UnknownHostException e) { // Do nothing } if (!isAllowed(connection)) { // Client cannot connect from this IP address so end the stream and // TCP connection Log.debug( "LocalClientSession: Closed connection to client attempting to connect from: " + hostAddress); // Include the not-authorized error in the response StreamError error = new StreamError(StreamError.Condition.not_authorized); connection.deliverRawText(error.toXML()); // Close the underlying connection connection.close(); return null; } } // Default language is English ("en"). String language = "en"; // Default to a version of "0.0". Clients written before the XMPP 1.0 spec may // not report a version in which case "0.0" should be assumed (per rfc3920 // section 4.4.1). int majorVersion = 0; int minorVersion = 0; for (int i = 0; i < xpp.getAttributeCount(); i++) { if ("lang".equals(xpp.getAttributeName(i))) { language = xpp.getAttributeValue(i); } if ("version".equals(xpp.getAttributeName(i))) { try { int[] version = decodeVersion(xpp.getAttributeValue(i)); majorVersion = version[0]; minorVersion = version[1]; } catch (Exception e) { Log.error(e.getMessage(), e); } } } // If the client supports a greater major version than the server, // set the version to the highest one the server supports. if (majorVersion > MAJOR_VERSION) { majorVersion = MAJOR_VERSION; minorVersion = MINOR_VERSION; } else if (majorVersion == MAJOR_VERSION) { // If the client supports a greater minor version than the // server, set the version to the highest one that the server // supports. if (minorVersion > MINOR_VERSION) { minorVersion = MINOR_VERSION; } } // Store language and version information in the connection. connection.setLanaguage(language); connection.setXMPPVersion(majorVersion, minorVersion); // Indicate the TLS policy to use for this connection if (!connection.isSecure()) { boolean hasCertificates = false; try { hasCertificates = SSLConfig.getKeyStore().size() > 0; } catch (Exception e) { Log.error(e.getMessage(), e); } Connection.TLSPolicy tlsPolicy = getTLSPolicy(); if (Connection.TLSPolicy.required == tlsPolicy && !hasCertificates) { Log.error( "Client session rejected. TLS is required but no certificates " + "were created."); return null; } // Set default TLS policy connection.setTlsPolicy(hasCertificates ? tlsPolicy : Connection.TLSPolicy.disabled); } else { // Set default TLS policy connection.setTlsPolicy(Connection.TLSPolicy.disabled); } // Indicate the compression policy to use for this connection connection.setCompressionPolicy(getCompressionPolicy()); // Create a ClientSession for this user. LocalClientSession session = SessionManager.getInstance().createClientSession(connection); // Build the start packet response StringBuilder sb = new StringBuilder(200); sb.append("<?xml version='1.0' encoding='"); sb.append(CHARSET); sb.append("'?>"); if (isFlashClient) { sb.append("<flash:stream xmlns:flash=\"http://www.jabber.com/streams/flash\" "); } else { sb.append("<stream:stream "); } sb.append("xmlns:stream=\"http://etherx.jabber.org/streams\" xmlns=\"jabber:client\" from=\""); sb.append(serverName); sb.append("\" id=\""); sb.append(session.getStreamID().toString()); sb.append("\" xml:lang=\""); sb.append(language); // Don't include version info if the version is 0.0. if (majorVersion != 0) { sb.append("\" version=\""); sb.append(majorVersion).append(".").append(minorVersion); } sb.append("\">"); connection.deliverRawText(sb.toString()); // If this is a "Jabber" connection, the session is now initialized and we can // return to allow normal packet parsing. if (majorVersion == 0) { return session; } // Otherwise, this is at least XMPP 1.0 so we need to announce stream features. sb = new StringBuilder(490); sb.append("<stream:features>"); if (connection.getTlsPolicy() != Connection.TLSPolicy.disabled) { sb.append("<starttls xmlns=\"urn:ietf:params:xml:ns:xmpp-tls\">"); if (connection.getTlsPolicy() == Connection.TLSPolicy.required) { sb.append("<required/>"); } sb.append("</starttls>"); } // Include available SASL Mechanisms sb.append(SASLAuthentication.getSASLMechanisms(session)); // Include Stream features String specificFeatures = session.getAvailableStreamFeatures(); if (specificFeatures != null) { sb.append(specificFeatures); } sb.append("</stream:features>"); connection.deliverRawText(sb.toString()); return session; }
/** * Returns true if the other peer of this session presented a self-signed certificate. When using * self-signed certificate for server-2-server sessions then SASL EXTERNAL will not be used and * instead server-dialback will be preferred for vcerifying the identify of the remote server. * * @return true if the other peer of this session presented a self-signed certificate. */ public boolean isUsingSelfSignedCertificate() { return conn.isUsingSelfSignedCertificate(); }
public String getHostAddress() throws UnknownHostException { return conn.getHostAddress(); }
public String getHostName() throws UnknownHostException { return conn.getHostName(); }
public boolean isClosed() { return conn.isClosed(); }
public boolean isSecure() { return conn.isSecure(); }
public boolean validate() { return conn.validate(); }
public void close() { if (conn != null) { conn.close(); } }
public void deliverRawText(String text) { if (conn != null) { conn.deliverRawText(text); } }