Example usage for org.dom4j Element getTextTrim

List of usage examples for org.dom4j Element getTextTrim

Introduction

In this page you can find the example usage for org.dom4j Element getTextTrim.

Prototype

String getTextTrim();

Source Link

Document

DOCUMENT ME!

Usage

From source file:org.jivesoftware.openfire.net.SASLAuthentication.java

License:Open Source License

/**
 * Handles the SASL authentication packet. The entity may be sending an initial
 * authentication request or a response to a challenge made by the server. The returned
 * value indicates whether the authentication has finished either successfully or not or
 * if the entity is expected to send a response to a challenge.
 *
 * @param session the session that is authenticating with the server.
 * @param doc the stanza sent by the authenticating entity.
 * @return value that indicates whether the authentication has finished either successfully
 *         or not or if the entity is expected to send a response to a challenge.
 * @throws UnsupportedEncodingException If UTF-8 charset is not supported.
 *///  w  w  w. ja v  a 2s  .c  o  m
public static Status handle(LocalSession session, Element doc) throws UnsupportedEncodingException {
    Status status;
    String mechanism;
    if (doc.getNamespace().asXML().equals(SASL_NAMESPACE)) {
        ElementType type = ElementType.valueof(doc.getName());
        switch (type) {
        case ABORT:
            authenticationFailed(session, Failure.ABORTED);
            status = Status.failed;
            break;
        case AUTH:
            mechanism = doc.attributeValue("mechanism");
            // http://xmpp.org/rfcs/rfc6120.html#sasl-errors-invalid-mechanism
            // The initiating entity did not specify a mechanism
            if (mechanism == null) {
                authenticationFailed(session, Failure.INVALID_MECHANISM);
                status = Status.failed;
                break;
            }
            // Store the requested SASL mechanism by the client
            session.setSessionData("SaslMechanism", mechanism);
            //Log.debug("SASLAuthentication.doHandshake() AUTH entered: "+mechanism);
            if (mechanism.equalsIgnoreCase("ANONYMOUS") && mechanisms.contains("ANONYMOUS")) {
                status = doAnonymousAuthentication(session);
            } else if (mechanism.equalsIgnoreCase("EXTERNAL")) {
                status = doExternalAuthentication(session, doc);
            } else if (mechanisms.contains(mechanism)) {
                // The selected SASL mechanism requires the server to send a challenge
                // to the client
                try {
                    Map<String, String> props = new TreeMap<String, String>();
                    props.put(Sasl.QOP, "auth");
                    if (mechanism.equals("GSSAPI")) {
                        props.put(Sasl.SERVER_AUTH, "TRUE");
                    }
                    SaslServer ss = Sasl.createSaslServer(mechanism, "xmpp",
                            JiveGlobals.getProperty("xmpp.fqdn", session.getServerName()), props,
                            new XMPPCallbackHandler());

                    if (ss == null) {
                        authenticationFailed(session, Failure.INVALID_MECHANISM);
                        return Status.failed;
                    }

                    // evaluateResponse doesn't like null parameter
                    byte[] token = new byte[0];
                    String value = doc.getTextTrim();
                    if (value.length() > 0) {
                        if (!BASE64_ENCODED.matcher(value).matches()) {
                            authenticationFailed(session, Failure.INCORRECT_ENCODING);
                            return Status.failed;
                        }
                        // If auth request includes a value then validate it
                        token = StringUtils.decodeBase64(value);
                        if (token == null) {
                            token = new byte[0];
                        }
                    }
                    if (mechanism.equals("DIGEST-MD5")) {
                        // RFC2831 (DIGEST-MD5) says the client MAY provide an initial response on subsequent
                        // authentication. Java SASL does not (currently) support this and thows an exception
                        // if we try.  This violates the RFC, so we just strip any initial token.
                        token = new byte[0];
                    }
                    byte[] challenge = ss.evaluateResponse(token);
                    if (ss.isComplete()) {
                        authenticationSuccessful(session, ss.getAuthorizationID(), challenge);
                        status = Status.authenticated;
                    } else {
                        // Send the challenge
                        sendChallenge(session, challenge);
                        status = Status.needResponse;
                    }
                    session.setSessionData("SaslServer", ss);
                } catch (SaslException e) {
                    Log.info("User Login Failed. " + e.getMessage());
                    authenticationFailed(session, Failure.NOT_AUTHORIZED);
                    status = Status.failed;
                }
            } else {
                Log.warn("Client wants to do a MECH we don't support: '" + mechanism + "'");
                authenticationFailed(session, Failure.INVALID_MECHANISM);
                status = Status.failed;
            }
            break;
        case RESPONSE:
            // Store the requested SASL mechanism by the client
            mechanism = (String) session.getSessionData("SaslMechanism");
            if (mechanism.equalsIgnoreCase("EXTERNAL")) {
                status = doExternalAuthentication(session, doc);
            } else if (mechanism.equalsIgnoreCase("JIVE-SHAREDSECRET")) {
                status = doSharedSecretAuthentication(session, doc);
            } else if (mechanisms.contains(mechanism)) {
                SaslServer ss = (SaslServer) session.getSessionData("SaslServer");
                if (ss != null) {
                    boolean ssComplete = ss.isComplete();
                    String response = doc.getTextTrim();
                    if (!BASE64_ENCODED.matcher(response).matches()) {
                        authenticationFailed(session, Failure.INCORRECT_ENCODING);
                        return Status.failed;
                    }
                    try {
                        if (ssComplete) {
                            authenticationSuccessful(session, ss.getAuthorizationID(), null);
                            status = Status.authenticated;
                        } else {
                            byte[] data = StringUtils.decodeBase64(response);
                            if (data == null) {
                                data = new byte[0];
                            }
                            byte[] challenge = ss.evaluateResponse(data);
                            if (ss.isComplete()) {
                                authenticationSuccessful(session, ss.getAuthorizationID(), challenge);
                                status = Status.authenticated;
                            } else {
                                // Send the challenge
                                sendChallenge(session, challenge);
                                status = Status.needResponse;
                            }
                        }
                    } catch (SaslException e) {
                        Log.debug("SASLAuthentication: SaslException", e);
                        authenticationFailed(session, Failure.NOT_AUTHORIZED);
                        status = Status.failed;
                    }
                } else {
                    Log.error("SaslServer is null, should be valid object instead.");
                    authenticationFailed(session, Failure.NOT_AUTHORIZED);
                    status = Status.failed;
                }
            } else {
                Log.warn("Client responded to a MECH we don't support: '" + mechanism + "'");
                authenticationFailed(session, Failure.INVALID_MECHANISM);
                status = Status.failed;
            }
            break;
        default:
            authenticationFailed(session, Failure.NOT_AUTHORIZED);
            status = Status.failed;
            // Ignore
            break;
        }
    } else {
        Log.debug("SASLAuthentication: Unknown namespace sent in auth element: " + doc.asXML());
        authenticationFailed(session, Failure.MALFORMED_REQUEST);
        status = Status.failed;
    }
    // Check if SASL authentication has finished so we can clean up temp information
    if (status == Status.failed || status == Status.authenticated) {
        // Remove the SaslServer from the Session
        session.removeSessionData("SaslServer");
        // Remove the requested SASL mechanism by the client
        session.removeSessionData("SaslMechanism");
    }
    return status;
}

From source file:org.jivesoftware.openfire.net.SASLAuthentication.java

License:Open Source License

private static Status doExternalAuthentication(LocalSession session, Element doc)
        throws UnsupportedEncodingException {
    // At this point the connection has already been secured using TLS

    if (session instanceof IncomingServerSession) {

        String hostname = doc.getTextTrim();
        if (hostname == null || hostname.length() == 0) {
            // No hostname was provided so send a challenge to get it
            sendChallenge(session, new byte[0]);
            return Status.needResponse;
        }/*  w ww.  j  av  a  2s .  c o m*/

        hostname = new String(StringUtils.decodeBase64(hostname), CHARSET);
        if (hostname.length() == 0) {
            hostname = null;
        }
        try {
            LocalIncomingServerSession svr = (LocalIncomingServerSession) session;
            String defHostname = svr.getDefaultIdentity();
            if (hostname == null) {
                hostname = defHostname;
            } else if (!hostname.equals(defHostname)) {
                // Mismatch; really odd.
                Log.info("SASLAuthentication rejected from='{}' and authzid='{}'", hostname, defHostname);
                authenticationFailed(session, Failure.NOT_AUTHORIZED);
                return Status.failed;
            }
        } catch (Exception e) {
            // Erm. Nothing?
        }
        if (hostname == null) {
            Log.info("No authzid supplied for anonymous session.");
            authenticationFailed(session, Failure.NOT_AUTHORIZED);
            return Status.failed;
        }
        // Check if certificate validation is disabled for s2s
        // Flag that indicates if certificates of the remote server should be validated.
        // Disabling certificate validation is not recommended for production environments.
        boolean verify = JiveGlobals.getBooleanProperty(ConnectionSettings.Server.TLS_CERTIFICATE_VERIFY, true);
        if (!verify) {
            authenticationSuccessful(session, hostname, null);
            return Status.authenticated;
        } else if (verifyCertificates(session.getConnection().getPeerCertificates(), hostname)) {
            authenticationSuccessful(session, hostname, null);
            LocalIncomingServerSession s = (LocalIncomingServerSession) session;
            if (s != null) {
                s.tlsAuth();
            }
            return Status.authenticated;
        }
    } else if (session instanceof LocalClientSession) {
        // Client EXTERNALL login
        Log.debug("SASLAuthentication: EXTERNAL authentication via SSL certs for c2s connection");

        // This may be null, we will deal with that later
        String username = new String(StringUtils.decodeBase64(doc.getTextTrim()), CHARSET);
        String principal = "";
        ArrayList<String> principals = new ArrayList<String>();
        Connection connection = session.getConnection();
        if (connection.getPeerCertificates().length < 1) {
            Log.debug("SASLAuthentication: EXTERNAL authentication requested, but no certificates found.");
            authenticationFailed(session, Failure.NOT_AUTHORIZED);
            return Status.failed;
        }

        X509Certificate trusted;
        try {
            trusted = CertificateManager.getEndEntityCertificate(connection.getPeerCertificates(),
                    SSLConfig.getKeyStore(), SSLConfig.gets2sTrustStore());
        } catch (IOException e) {
            trusted = null;
        }
        if (trusted == null) {
            Log.debug("SASLAuthentication: EXTERNAL authentication requested, but EE cert untrusted.");
            authenticationFailed(session, Failure.NOT_AUTHORIZED);
            return Status.failed;
        }
        principals.addAll(CertificateManager.getPeerIdentities((X509Certificate) trusted));

        if (principals.size() == 1) {
            principal = principals.get(0);
        } else if (principals.size() > 1) {
            Log.debug(
                    "SASLAuthentication: EXTERNAL authentication: more than one principal found, using first.");
            principal = principals.get(0);
        } else {
            Log.debug("SASLAuthentication: EXTERNAL authentication: No principals found.");
        }

        if (username == null || username.length() == 0) {
            // No username was provided, according to XEP-0178 we need to:
            //    * attempt to get it from the cert first
            //    * have the server assign one

            // There shouldn't be more than a few principals in here. One ideally
            // We set principal to the first one in the list to have a sane default
            // If this list is empty, then the cert had no identity at all, which
            // will cause an authorization failure
            for (String princ : principals) {
                String u = AuthorizationManager.map(princ);
                if (!u.equals(princ)) {
                    username = u;
                    principal = princ;
                    break;
                }
            }
            if (username == null || username.length() == 0) {
                // Still no username.  Punt.
                username = principal;
            }
            Log.debug("SASLAuthentication: no username requested, using " + username);
        }

        //Its possible that either/both username and principal are null here
        //The providers should not allow a null authorization
        if (AuthorizationManager.authorize(username, principal)) {
            Log.debug("SASLAuthentication: " + principal + " authorized to " + username);
            authenticationSuccessful(session, username, null);
            return Status.authenticated;
        }
    } else {
        Log.debug("SASLAuthentication: unknown session type. Cannot perform EXTERNAL authentication");
    }
    authenticationFailed(session, Failure.NOT_AUTHORIZED);
    return Status.failed;
}

From source file:org.jivesoftware.openfire.net.SASLAuthentication.java

License:Open Source License

private static Status doSharedSecretAuthentication(LocalSession session, Element doc)
        throws UnsupportedEncodingException {
    String secretDigest;/*  w ww  .  j a  v  a2 s  . co m*/
    String response = doc.getTextTrim();
    if (response == null || response.length() == 0) {
        // No info was provided so send a challenge to get it
        sendChallenge(session, new byte[0]);
        return Status.needResponse;
    }

    // Parse data and obtain username & password
    String data = new String(StringUtils.decodeBase64(response), CHARSET);
    StringTokenizer tokens = new StringTokenizer(data, "\0");
    tokens.nextToken();
    secretDigest = tokens.nextToken();
    if (authenticateSharedSecret(secretDigest)) {
        authenticationSuccessful(session, null, null);
        return Status.authenticated;
    }
    // Otherwise, authentication failed.
    authenticationFailed(session, Failure.NOT_AUTHORIZED);
    return Status.failed;
}

From source file:org.jivesoftware.openfire.plugin.SearchPlugin.java

License:Open Source License

/**
 * Processes an IQ stanza of type 'set', which in the context of 'Jabber Search' is a search request.
 * // w  w  w  . j a va2  s . c o  m
 * @param packet
 *            An IQ stanza of type 'get'
 * @return A result IQ stanza that contains the possbile search fields.
 */
private IQ processSetPacket(IQ packet) {
    if (!packet.getType().equals(IQ.Type.set)) {
        throw new IllegalArgumentException("This method only accepts 'set' typed IQ stanzas as an argument.");
    }

    JID fromJID = packet.getFrom();

    final IQ resultIQ;

    // check if the request complies to the XEP-0055 standards
    if (!isValidSearchRequest(packet)) {
        resultIQ = IQ.createResultIQ(packet);
        resultIQ.setError(Condition.bad_request);
        return resultIQ;
    }

    final Element incomingForm = packet.getChildElement();
    final boolean isDataFormQuery = (incomingForm.element(QName.get("x", "jabber:x:data")) != null);

    final Element rsmElement = incomingForm
            .element(QName.get("set", ResultSet.NAMESPACE_RESULT_SET_MANAGEMENT));

    if (rsmElement != null) {
        final Element maxElement = rsmElement.element("max");
        final Element startIndexElement = rsmElement.element("index");

        int startIndex = 0;
        if (startIndexElement != null) {
            startIndex = Integer.parseInt(startIndexElement.getTextTrim());
        }

        int max = -1;
        if (maxElement != null) {
            max = Integer.parseInt(maxElement.getTextTrim());
        }

        final Set<User> searchResults = performSearch(incomingForm, startIndex, max);

        if (groupOnly) {
            Collection<Group> groups = GroupManager.getInstance().getGroups(fromJID);
            Set<User> allSearchResults = new HashSet<User>(searchResults);
            searchResults.clear();
            for (User user : allSearchResults) {
                for (Group group : groups) {
                    if (group.isUser(user.getUID())) {
                        searchResults.add(user);
                    }
                }
            }
        }

        // apply RSM
        final List<User> rsmResults;
        final ResultSet<User> rs = new ResultSetImpl<User>(searchResults);
        try {
            rsmResults = rs.applyRSMDirectives(rsmElement);
        } catch (NullPointerException e) {
            final IQ itemNotFound = IQ.createResultIQ(packet);
            itemNotFound.setError(Condition.item_not_found);
            return itemNotFound;
        }
        if (isDataFormQuery) {
            resultIQ = replyDataFormResult(rsmResults, packet);
        } else {
            resultIQ = replyNonDataFormResult(rsmResults, packet);
        }

        // add the additional 'set' element.
        final Element set = rs.generateSetElementFromResults(rsmResults);
        resultIQ.getChildElement().add(set);

    } else {
        final Set<User> searchResults = performSearch(incomingForm);

        if (groupOnly) {
            Collection<Group> groups = GroupManager.getInstance().getGroups(fromJID);
            Set<User> allSearchResults = new HashSet<User>(searchResults);
            searchResults.clear();
            for (User user : allSearchResults) {
                for (Group group : groups) {
                    if (group.isUser(user.getUID())) {
                        searchResults.add(user);
                    }
                }
            }
        }

        // don't apply RSM
        if (isDataFormQuery) {
            resultIQ = replyDataFormResult(searchResults, packet);
        } else {
            resultIQ = replyNonDataFormResult(searchResults, packet);
        }
    }

    return resultIQ;
}

From source file:org.jivesoftware.openfire.server.ServerDialback.java

License:Open Source License

/**
 * Returns true if the domain requested by the remote server was validated by the Authoritative
 * Server. To validate the domain a new TCP connection will be established to the
 * Authoritative Server. The Authoritative Server may be the same Originating Server or
 * some other machine in the Originating Server's network.<p>
 *
 * If the domain was not valid or some error occurred while validating the domain then the
 * underlying TCP connection may be closed.
 *
 * @param doc the request for validating the new domain.
 * @param streamID the stream id generated by this server for the Originating Server.
 * @return true if the requested domain is valid.
 *///from  w w w . j  ava  2  s.c o  m
public boolean validateRemoteDomain(Element doc, StreamID streamID) {
    StringBuilder sb;
    String recipient = doc.attributeValue("to");
    String hostname = doc.attributeValue("from");
    Log.debug("ServerDialback: RS - Received dialback key from host: " + hostname + " to: " + recipient);
    if (!RemoteServerManager.canAccess(hostname)) {
        // Remote server is not allowed to establish a connection to this server
        connection.deliverRawText(new StreamError(StreamError.Condition.policy_violation).toXML());
        // Close the underlying connection
        connection.close();
        Log.debug("ServerDialback: RS - Error, hostname is not allowed to establish a connection to "
                + "this server: " + recipient);
        return false;
    } else if (isHostUnknown(recipient)) {
        dialbackError(recipient, hostname, new PacketError(PacketError.Condition.item_not_found,
                PacketError.Type.cancel, "Service not hosted here"));
        Log.debug("ServerDialback: RS - Error, hostname not recognized: " + recipient);
        return false;
    } else {
        // Check if the remote server already has a connection to the target domain/subdomain
        boolean alreadyExists = false;
        for (IncomingServerSession session : sessionManager.getIncomingServerSessions(hostname)) {
            if (recipient.equals(session.getLocalDomain())) {
                alreadyExists = true;
            }
        }
        if (alreadyExists && !sessionManager.isMultipleServerConnectionsAllowed()) {
            dialbackError(recipient, hostname, new PacketError(PacketError.Condition.resource_constraint,
                    PacketError.Type.cancel, "Incoming session already exists"));
            Log.debug("ServerDialback: RS - Error, incoming connection already exists from: " + hostname);
            return false;
        } else {
            if (SASLAuthentication.verifyCertificates(connection.getPeerCertificates(), hostname)) {
                // If the remote host passes strong auth, just skip the dialback.
                Log.debug("ServerDialback: RS - Sending key verification result to OS: " + hostname);
                sb = new StringBuilder();
                sb.append("<db:result");
                sb.append(" from=\"").append(recipient).append("\"");
                sb.append(" to=\"").append(hostname).append("\"");
                sb.append(" type=\"valid\"");
                sb.append("/>");
                connection.deliverRawText(sb.toString());
                return true;
            }
            String key = doc.getTextTrim();

            // Get a list of real hostnames and try to connect using DNS lookup of the specified domain
            List<DNSUtil.HostAddress> hosts = DNSUtil.resolveXMPPDomain(hostname,
                    RemoteServerManager.getPortForServer(hostname));
            Socket socket = new Socket();
            String realHostname = null;
            int realPort;
            for (Iterator<DNSUtil.HostAddress> it = hosts.iterator(); it.hasNext();) {
                try {
                    DNSUtil.HostAddress address = it.next();
                    realHostname = address.getHost();
                    realPort = address.getPort();
                    Log.debug("ServerDialback: RS - Trying to connect to Authoritative Server: " + hostname
                            + "(DNS lookup: " + realHostname + ":" + realPort + ")");
                    // Establish a TCP connection to the Receiving Server
                    socket.connect(new InetSocketAddress(realHostname, realPort),
                            RemoteServerManager.getSocketTimeout());
                    Log.debug("ServerDialback: RS - Connection to AS: " + hostname + " successful");
                    break;
                } catch (Exception e) {
                    Log.warn("Error trying to connect to remote server: " + hostname + "(DNS lookup: "
                            + realHostname + ")", e);
                }
            }
            if (!socket.isConnected()) {
                dialbackError(recipient, hostname,
                        new PacketError(PacketError.Condition.remote_server_not_found, PacketError.Type.cancel,
                                "Unable to connect to authoritative server"));
                Log.warn("No server available for verifying key of remote server: " + hostname);
                try {
                    socket.close();
                } catch (IOException e) {
                    Log.warn("Socket error on close", e);
                }
                return false;
            }

            try {
                VerifyResult result = verifyKey(key, streamID.toString(), recipient, hostname, socket);

                switch (result) {
                case valid:
                case invalid:
                    boolean valid = (result == VerifyResult.valid);
                    Log.debug("ServerDialback: RS - Sending key verification result to OS: " + hostname);
                    sb = new StringBuilder();
                    sb.append("<db:result");
                    sb.append(" from=\"").append(recipient).append("\"");
                    sb.append(" to=\"").append(hostname).append("\"");
                    sb.append(" type=\"");
                    sb.append(valid ? "valid" : "invalid");
                    sb.append("\"/>");
                    connection.deliverRawText(sb.toString());

                    if (!valid) {
                        // Close the underlying connection
                        connection.close();
                    }
                    return valid;
                default:
                    break;
                }
                dialbackError(recipient, hostname, new PacketError(PacketError.Condition.remote_server_timeout,
                        PacketError.Type.cancel, "Authoritative server returned error"));
                return false;
            } catch (Exception e) {
                dialbackError(recipient, hostname, new PacketError(PacketError.Condition.remote_server_timeout,
                        PacketError.Type.cancel, "Authoritative server failed"));
                Log.warn("Error verifying key of remote server: " + hostname, e);
                return false;
            }
        }
    }
}

From source file:org.jivesoftware.openfire.server.ServerDialback.java

License:Open Source License

/**
 * Verifies the key sent by a Receiving Server. This server will be acting as the
 * Authoritative Server when executing this method. The remote server may have established
 * a new connection to the Authoritative Server (i.e. this server) for verifying the key
 * or it may be reusing an existing incoming connection.
 *
 * @param doc the Element that contains the key to verify.
 * @param connection the connection to use for sending the verification result
 * @return true if the key was verified.
 *//*w  ww  .jav a2s  . co  m*/
public static boolean verifyReceivedKey(Element doc, Connection connection) {
    String verifyFROM = doc.attributeValue("from");
    String verifyTO = doc.attributeValue("to");
    String key = doc.getTextTrim();
    String id = doc.attributeValue("id");
    Log.debug("ServerDialback: AS - Verifying key for host: " + verifyFROM + " id: " + id);

    // TODO If the value of the 'to' address does not match a recognized hostname,
    // then generate a <host-unknown/> stream error condition
    // TODO If the value of the 'from' address does not match the hostname
    // represented by the Receiving Server when opening the TCP connection, then
    // generate an <invalid-from/> stream error condition

    // Verify the received key
    // Created the expected key based on the received ID value and the shared secret
    String expectedKey = AuthFactory.createDigest(id, getSecretkey());
    boolean verified = expectedKey.equals(key);

    // Send the result of the key verification
    StringBuilder sb = new StringBuilder();
    sb.append("<db:verify");
    sb.append(" from=\"").append(verifyTO).append("\"");
    sb.append(" to=\"").append(verifyFROM).append("\"");
    sb.append(" type=\"");
    sb.append(verified ? "valid" : "invalid");
    sb.append("\" id=\"").append(id).append("\"/>");
    connection.deliverRawText(sb.toString());
    Log.debug("ServerDialback: AS - Key was: " + (verified ? "VALID" : "INVALID") + " for host: " + verifyFROM
            + " id: " + id);
    return verified;
}

From source file:org.jivesoftware.openfire.session.LocalOutgoingServerSession.java

License:Open Source License

private static LocalOutgoingServerSession secureAndAuthenticate(String hostname, SocketConnection connection,
        XMPPPacketReader reader, StringBuilder openingStream, String domain) throws Exception {
    final Logger log = LoggerFactory
            .getLogger(LocalOutgoingServerSession.class.getName() + "['" + hostname + "']");
    Element features;//  ww  w  .  j  a v a 2 s . c o m
    log.debug("Indicating we want TLS to " + hostname);
    connection.deliverRawText("<starttls xmlns='urn:ietf:params:xml:ns:xmpp-tls'/>");

    MXParser xpp = reader.getXPPParser();
    // Wait for the <proceed> response
    Element proceed = reader.parseDocument().getRootElement();
    if (proceed != null && proceed.getName().equals("proceed")) {
        log.debug("Negotiating TLS...");
        try {
            boolean needed = JiveGlobals.getBooleanProperty(ConnectionSettings.Server.TLS_CERTIFICATE_VERIFY,
                    true)
                    && JiveGlobals.getBooleanProperty(ConnectionSettings.Server.TLS_CERTIFICATE_CHAIN_VERIFY,
                            true)
                    && !JiveGlobals.getBooleanProperty(ConnectionSettings.Server.TLS_ACCEPT_SELFSIGNED_CERTS,
                            false);
            connection.startTLS(true, hostname,
                    needed ? Connection.ClientAuth.needed : Connection.ClientAuth.wanted);
        } catch (Exception e) {
            log.debug("Got an exception whilst negotiating TLS: " + e.getMessage());
            throw e;
        }
        log.debug("TLS negotiation was successful.");
        if (!SASLAuthentication.verifyCertificates(connection.getPeerCertificates(), hostname)) {
            log.debug("X.509/PKIX failure on outbound session");
            if (ServerDialback.isEnabled() || ServerDialback.isEnabledForSelfSigned()) {
                log.debug("Will continue with dialback.");
            } else {
                log.warn("No TLS auth, but TLS auth required.");
                return null;
            }
        }

        // TLS negotiation was successful so initiate a new stream
        connection.deliverRawText(openingStream.toString());

        // Reset the parser to use the new secured reader
        xpp.setInput(new InputStreamReader(connection.getTLSStreamHandler().getInputStream(), CHARSET));
        // Skip new stream element
        for (int eventType = xpp.getEventType(); eventType != XmlPullParser.START_TAG;) {
            eventType = xpp.next();
        }
        // Get the stream ID 
        String id = xpp.getAttributeValue("", "id");
        // Get new stream features
        features = reader.parseDocument().getRootElement();
        if (features != null) {
            // Check if we can use stream compression
            String policyName = JiveGlobals.getProperty(ConnectionSettings.Server.COMPRESSION_SETTINGS,
                    Connection.CompressionPolicy.disabled.toString());
            Connection.CompressionPolicy compressionPolicy = Connection.CompressionPolicy.valueOf(policyName);
            if (Connection.CompressionPolicy.optional == compressionPolicy) {
                // Verify if the remote server supports stream compression
                Element compression = features.element("compression");
                if (compression != null) {
                    boolean zlibSupported = false;
                    Iterator it = compression.elementIterator("method");
                    while (it.hasNext()) {
                        Element method = (Element) it.next();
                        if ("zlib".equals(method.getTextTrim())) {
                            zlibSupported = true;
                        }
                    }
                    if (zlibSupported) {
                        log.debug("Suppressing request to perform compression; unsupported in this version.");
                        zlibSupported = false;
                    }
                    if (zlibSupported) {
                        log.debug("Requesting stream compression (zlib).");
                        connection.deliverRawText(
                                "<compress xmlns='http://jabber.org/protocol/compress'><method>zlib</method></compress>");
                        // Check if we are good to start compression
                        Element answer = reader.parseDocument().getRootElement();
                        if ("compressed".equals(answer.getName())) {
                            // Server confirmed that we can use zlib compression
                            connection.addCompression();
                            connection.startCompression();
                            log.debug("Stream compression was successful.");
                            // Stream compression was successful so initiate a new stream
                            connection.deliverRawText(openingStream.toString());
                            // Reset the parser to use stream compression over TLS
                            ZInputStream in = new ZInputStream(
                                    connection.getTLSStreamHandler().getInputStream());
                            in.setFlushMode(JZlib.Z_PARTIAL_FLUSH);
                            xpp.setInput(new InputStreamReader(in, CHARSET));
                            // Skip the opening stream sent by the server
                            for (int eventType = xpp.getEventType(); eventType != XmlPullParser.START_TAG;) {
                                eventType = xpp.next();
                            }
                            // Get new stream features
                            features = reader.parseDocument().getRootElement();
                            if (features == null) {
                                log.debug("Error, EXTERNAL SASL was not offered.");
                                return null;
                            }
                        } else {
                            log.debug("Stream compression was rejected by " + hostname);
                        }
                    } else {
                        log.debug("Stream compression found but zlib method is not supported by " + hostname);
                    }
                } else {
                    log.debug("Stream compression not supported by " + hostname);
                }
            }

            // Bookkeeping: determine what functionality the remote server offers.
            boolean saslEXTERNALoffered = false;
            if (features != null) {
                if (features.element("mechanisms") != null) {
                    Iterator<Element> it = features.element("mechanisms").elementIterator();
                    while (it.hasNext()) {
                        Element mechanism = it.next();
                        if ("EXTERNAL".equals(mechanism.getTextTrim())) {
                            saslEXTERNALoffered = true;
                            break;
                        }
                    }
                }
            }
            final boolean dialbackOffered = features.element("dialback") != null;

            log.debug("Offering dialback functionality: {}", dialbackOffered);
            log.debug("Offering EXTERNAL SASL: {}", saslEXTERNALoffered);

            LocalOutgoingServerSession result = null;
            // first, try SASL
            if (saslEXTERNALoffered) {
                result = attemptSASLexternal(connection, xpp, reader, domain, hostname, id, openingStream);
            }
            if (result == null) {
                // SASL unavailable or failed, try dialback.
                result = attemptDialbackOverTLS(connection, reader, domain, hostname, id);
            }

            return result;
        } else {
            log.debug(
                    "Cannot create outgoing server session, as neither SASL mechanisms nor SERVER DIALBACK were offered by "
                            + hostname);
            return null;
        }
    } else {
        log.debug("Error, <proceed> was not received!");
        return null;
    }
}

From source file:org.jivesoftware.openfire.sip.log.LogListenerImpl.java

License:Open Source License

public IQ logReceived(IQ iq) {

    String username = iq.getTo().toBareJID().split("@")[0];

    if (username != null) {

        CallLog callLog = new CallLog(username);
        Element pe = iq.getChildElement().element("callLog");

        if (pe != null) {

            Element numA = pe.element("numA");
            Element numB = pe.element("numB");
            Element duration = pe.element("duration");
            Element type = pe.element("type");

            callLog.setNumA((numA != null) ? numA.getTextTrim() : "");
            callLog.setNumB((numB != null) ? numB.getTextTrim() : "");
            callLog.setDateTime(new Date().getTime());
            callLog.setDuration((duration != null) ? Integer.parseInt(duration.getText()) : 0);
            if (type != null && "loss".equals(type.getTextTrim())) {
                // Backwards compatibility change
                type.setText("missed");
            }/*ww w. j a  v  a 2s  . co m*/
            callLog.setType((type != null) ? CallLog.Type.valueOf(type.getTextTrim()) : CallLog.Type.dialed);

            try {
                CallLogDAO.insert(callLog);
            } catch (SQLException e) {
                Log.error(e.getMessage(), e);
            }
        }
    }
    iq.setType(IQ.Type.result);

    iq.deleteExtension(CallLogExtension.ELEMENT_NAME, CallLogExtension.NAMESPACE);

    Element childElement = iq.getChildElement();
    if (childElement != null) {
        Element childElementCopy = childElement.createCopy();
        iq.setChildElement(childElementCopy);
    }
    return iq;
}

From source file:org.jivesoftware.openfire.sip.sipaccount.SipComponent.java

License:Open Source License

private void processIQ(IQ iq) {
    IQ reply = IQ.createResultIQ(iq);/*  www.  java 2s.co m*/
    String namespace = iq.getChildElement().getNamespaceURI();
    Element childElement = iq.getChildElement().createCopy();
    reply.setChildElement(childElement);

    if ("http://jabber.org/protocol/disco#info".equals(namespace)) {
        if (iq.getTo().getNode() == null) {
            // Return service identity and features
            Element identity = childElement.addElement("identity");
            identity.addAttribute("category", "component");
            identity.addAttribute("type", "generic");
            identity.addAttribute("name", "SIP Controller");
            childElement.addElement("feature").addAttribute("var", "http://jabber.org/protocol/disco#info");
            childElement.addElement("feature").addAttribute("var",
                    "http://www.jivesoftware.com/protocol/sipark");

        }
    } else if (NAMESPACE.equals(namespace)) {
        if (iq.getTo().getNode() == null && iq.getFrom() != null) {

            SipAccount sipAccount = SipAccountDAO.getAccountByUser(iq.getFrom().toBareJID().split("@")[0]);

            if (iq.getChildElement().element("status") == null) {
                if (sipAccount != null && sipAccount.isEnabled()) {
                    // There is a SIP mapping for this user so return mapping information
                    Element registration = childElement.addElement("registration");
                    registration.addElement("jid")
                            .setText(sipAccount.getUsername() + "@" + componentManager.getServerName());
                    registration.addElement("username").setText(sipAccount.getSipUsername());
                    registration.addElement("authUsername").setText(sipAccount.getAuthUsername());
                    registration.addElement("displayPhoneNum").setText(sipAccount.getDisplayName());
                    registration.addElement("password").setText(sipAccount.getPassword());
                    registration.addElement("server").setText(sipAccount.getServer());
                    registration.addElement("stunServer").setText(sipAccount.getStunServer());
                    registration.addElement("stunPort").setText(sipAccount.getStunPort());
                    registration.addElement("useStun").setText(String.valueOf(sipAccount.isUseStun()));
                    registration.addElement("voicemail").setText(sipAccount.getVoiceMailNumber());
                    registration.addElement("enabled").setText(String.valueOf(sipAccount.isEnabled()));
                    registration.addElement("outboundproxy").setText(sipAccount.getOutboundproxy());
                    registration.addElement("promptCredentials")
                            .setText(String.valueOf(sipAccount.isPromptCredentials()));
                } else {
                    // No SIP mapping was found
                    reply.getChildElement().addAttribute("type", "unregistered");
                }
            } else {
                if (sipAccount != null) {
                    Element status = iq.getChildElement().element("status");
                    if (!status.getTextTrim().equals("")) {
                        sipAccount.setStatus(SipRegisterStatus.valueOf(status.getTextTrim()));
                        try {
                            SipAccountDAO.update(sipAccount);
                        } catch (SQLException e) {
                            Log.error(e.getMessage(), e);
                        }
                    }
                }
            }
        }
    } else {
        // Answer an error since the server can't handle the requested
        // namespace
        reply.setError(PacketError.Condition.service_unavailable);
    }
    try {
        componentManager.sendPacket(this, reply);
    } catch (Exception e) {
        Log.error(e.getMessage(), e);
    }
    Log.debug("PACKET SENT: " + reply.toXML());
}

From source file:org.jivesoftware.openfire.vcard.VCardManager.java

License:Open Source License

/**
 * Returns the user's vCard information for a given vcard property name. If the property
 * has no defined text then an empty string will be returned. However, if the property
 * does not exist then a <tt>null</tt> value will be answered. Advanced user systems can
 * use vCard information to link to user directory information or store other relevant
 * user information.//from ww  w .  j  a  va  2 s.co m
 * <p>
 * Note that many elements in the vCard may have the same path so the returned value in that
 * case will be the first found element. For instance, "ADR:STREET" may be present in
 * many addresses of the user. Use {@link #getVCard(String)} to get the whole vCard of
 * the user.</p>
 *
 * @param username The username of the user to return his vCard property.
 * @param name     The name of the vcard property to retrieve encoded with ':' to denote
 *                 the path.
 * @return The vCard value found
 */
public String getVCardProperty(String username, String name) {
    String answer = null;
    Element vCardElement = getOrLoadVCard(username);
    if (vCardElement != null) {
        // A vCard was found for this user so now look for the correct element
        Element subElement = null;
        StringTokenizer tokenizer = new StringTokenizer(name, ":");
        while (tokenizer.hasMoreTokens()) {
            String tok = tokenizer.nextToken();
            if (subElement == null) {
                subElement = vCardElement.element(tok);
            } else {
                subElement = subElement.element(tok);
            }
            if (subElement == null) {
                break;
            }
        }
        if (subElement != null) {
            answer = subElement.getTextTrim();
        }
    }
    return answer;
}