qflag.ucstar.plugin.hanlde.IQXStandardAllAuthHandler.java Source code

Java tutorial

Introduction

Here is the source code for qflag.ucstar.plugin.hanlde.IQXStandardAllAuthHandler.java

Source

/**
 * $RCSfile$
 * $Revision: 2747 $
 * $Date: 2005-08-31 15:12:28 -0300 (Wed, 31 Aug 2005) $
 *
 * Copyright (C) 2004 Jive Software. All rights reserved.
 *
 * This software is published under the terms of the GNU Public License (GPL),
 * a copy of which is included in this distribution.
 */

package qflag.ucstar.plugin.hanlde;

import java.util.ArrayList;
import java.util.Collection;
import java.util.List;

import org.dom4j.DocumentHelper;
import org.dom4j.Element;
import org.dom4j.QName;
import org.jivesoftware.stringprep.Stringprep;
import org.jivesoftware.stringprep.StringprepException;
import org.jivesoftware.util.JiveGlobals;
import org.jivesoftware.util.LocaleUtils;
import org.jivesoftware.util.Log;
import org.jivesoftware.wildfire.ClientSession;
import org.jivesoftware.wildfire.ClusterSessionConnection;
import org.jivesoftware.wildfire.Connection;
import org.jivesoftware.wildfire.IQHandlerInfo;
import org.jivesoftware.wildfire.PacketException;
import org.jivesoftware.wildfire.Session;
import org.jivesoftware.wildfire.SessionManager;
import org.jivesoftware.wildfire.XMPPServer;
import org.jivesoftware.wildfire.auth.AuthFactory;
import org.jivesoftware.wildfire.auth.AuthToken;
import org.jivesoftware.wildfire.auth.UnauthorizedException;
import org.jivesoftware.wildfire.handler.IQAuthInfo;
import org.jivesoftware.wildfire.handler.IQHandler;
import org.jivesoftware.wildfire.nio.NIOConnection;
import org.jivesoftware.wildfire.user.User;
import org.jivesoftware.wildfire.user.UserManager;
import org.jivesoftware.wildfire.user.UserNotFoundException;
import org.xmpp.packet.IQ;
import org.xmpp.packet.JID;
import org.xmpp.packet.PacketError;
import org.xmpp.packet.StreamError;

import qflag.ucstar.TradeSysManager;
import qflag.ucstar.audit.LoginLimitManager;
import qflag.ucstar.base.properties.PropertiesConstants;
import qflag.ucstar.crypt.CryptManager;
import qflag.ucstar.exception.UcstarLicenseExpiredException;
import qflag.ucstar.license.LicenseManagerCenter;
import qflag.ucstar.license.UcstarLicenseInfo;
import qflag.ucstar.plugin.ucpostbox.manager.UcpostBoxCofing;
import qflag.ucstar.sessionbind.SessionBindManager;

/**
 * Implements the TYPE_IQ jabber:iq:auth protocol (plain only). Clients
 * use this protocol to authenticate with the server. A 'get' query
 * runs an authentication probe with a given user name. Return the
 * authentication form or an error indicating the user is not
 * registered on the server.<p>
 *
 * A 'set' query authenticates with information given in the
 * authentication form. An authenticated session may reset their
 * authentication information using a 'set' query.
 *
 * <h2>Assumptions</h2>
 * This handler assumes that the request is addressed to the server.
 * An appropriate TYPE_IQ tag matcher should be placed in front of this
 * one to route TYPE_IQ requests not addressed to the server to
 * another channel (probably for direct delivery to the recipient).
 *
 * @author Iain Shigeoka
 */
public class IQXStandardAllAuthHandler extends IQHandler implements IQAuthInfo {

    private static boolean anonymousAllowed;

    private Element probeResponse;
    private IQHandlerInfo info;

    private UserManager userManager;
    private XMPPServer localServer;
    private SessionManager sessionManager;

    /**
     * Clients are not authenticated when accessing this handler.
     */
    public IQXStandardAllAuthHandler() {
        super("XMPP Authentication handler");
        info = new IQHandlerInfo("query", "jabber:iq:auth");

        probeResponse = DocumentHelper.createElement(QName.get("query", "jabber:iq:auth"));
        probeResponse.addElement("username");
        if (AuthFactory.isPlainSupported()) {
            probeResponse.addElement("password");
        }
        if (AuthFactory.isDigestSupported()) {
            probeResponse.addElement("digest");
        }
        probeResponse.addElement("resource");
        anonymousAllowed = "true".equals(JiveGlobals.getProperty("xmpp.auth.anonymous"));
    }

    public IQ handleIQ(IQ packet) throws UnauthorizedException, PacketException {
        ClientSession session = sessionManager.getSession(packet.getFrom());
        // If no session was found then answer an error (if possible)
        if (session == null) {
            Log.error("Error during authentication. Session not found in "
                    + sessionManager.getPreAuthenticatedKeys() + " for key " + packet.getFrom());
            // This error packet will probably won't make it through
            IQ reply = IQ.createResultIQ(packet);
            reply.setChildElement(packet.getChildElement().createCopy());
            reply.setError(PacketError.Condition.internal_server_error);
            return reply;
        }
        IQ response;
        try {
            Element iq = packet.getElement();
            Element query = iq.element("query");
            Element queryResponse = probeResponse.createCopy();
            if (IQ.Type.get == packet.getType()) {
                String username = query.elementTextTrim("username");
                if (username != null) {
                    queryResponse.element("username").setText(username);
                }
                response = IQ.createResultIQ(packet);
                response.setChildElement(queryResponse);
                // This is a workaround. Since we don't want to have an incorrect TO attribute
                // value we need to clean up the TO attribute and send directly the response.
                // The TO attribute will contain an incorrect value since we are setting a fake
                // JID until the user actually authenticates with the server.
                if (session.getStatus() != Session.STATUS_AUTHENTICATED) {
                    response.setTo((JID) null);
                }
            }
            // Otherwise set query
            else {
                if (query.elements().isEmpty()) {
                    // Anonymous authentication
                    response = anonymousLogin(session, packet);
                } else {
                    String username = JiveGlobals.nullToEmpty(query.elementTextTrim("username"));
                    // Login authentication
                    String password = query.elementTextTrim("password");
                    String digest = null;
                    if (query.element("digest") != null) {
                        digest = query.elementTextTrim("digest").toLowerCase();
                    }

                    // If we're already logged in, this is a password reset
                    if (session.getStatus() == Session.STATUS_AUTHENTICATED) {
                        response = passwordReset(password, packet, username, session);
                    } else {
                        // it is an auth attempt
                        response = login(username, query, packet, password, session, digest);
                    }
                }
            }
        } catch (UserNotFoundException e) {
            response = IQ.createResultIQ(packet);
            response.setChildElement(packet.getChildElement().createCopy());
            response.setError(PacketError.Condition.not_authorized);
        } catch (UnauthorizedException e) {
            response = IQ.createResultIQ(packet);
            response.setChildElement(packet.getChildElement().createCopy());
            response.setError(PacketError.Condition.not_authorized);
        }
        // Send the response directly since we want to be sure that we are sending it back
        // to the correct session. Any other session of the same user but with different
        // resource is incorrect.
        session.process(response);
        return null;
    }

    private IQ login(String username, Element iq, IQ packet, String password, ClientSession session, String digest)
            throws UnauthorizedException, UserNotFoundException {
        // Verify that specified resource is not violating any string prep rule
        // add by rwl , user limit
        LoginLimitManager.getInstance().checkUserLimit();

        //add by polarbear , 2009-6-1, license?
        try {
            LoginLimitManager.getInstance().checkLicenseExpired();
        } catch (UcstarLicenseExpiredException e2) {
            Log.error(e2);
            IQ result = IQ.createResultIQ(packet);
            result.setError(PacketError.Condition.license_expired);
            return result;
        }

        String resource = iq.elementTextTrim("resource");
        if (resource != null) {
            try {
                resource = Stringprep.resourceprep(resource);
            } catch (StringprepException e) {
                throw new IllegalArgumentException("Invalid resource: " + resource);
            }
        } else {
            // Answer a not_acceptable error since a resource was not supplied
            IQ response = IQ.createResultIQ(packet);
            response.setChildElement(packet.getChildElement().createCopy());
            response.setError(PacketError.Condition.not_acceptable);
            return response;
        }
        username = username.toLowerCase();

        //add by rwl , ??admin
        try {
            LoginLimitManager.getInstance().checkUser(username, resource);
        } catch (Exception e1) {
            Log.error(e1.getMessage());
            IQ response = IQ.createResultIQ(packet);
            response.setChildElement(packet.getChildElement().createCopy());
            response.setError(PacketError.Condition.not_acceptable);
            return response;
        }

        //      //add by polarbear , 2008-6-5, ??
        //        String encryptedPassword = iq.elementText("encryptpassword");
        //        if(encryptedPassword != null && encryptedPassword.length() > 0){
        //           password = JiveGlobals.decordByDES(encryptedPassword);
        //        }
        //add by polarbear , 2008-6-5, ??
        String encryptedPassword = iq.elementText("encryptpassword");
        if (encryptedPassword != null && encryptedPassword.length() > 0) {
            password = CryptManager.getInstance().decryptedLoginStr(encryptedPassword);
        }

        //add by polarbear , 2009-3-30, MD5?
        String md5Password = iq.elementText("md5password");

        //??
        AuthToken token = null;
        //String type = iq.attributeValue("type");
        //if(type != null && type.equals("ssologin")) { //?
        String sessionId = iq.elementText("sessionkey");

        //add by polarbear , 2008-8-7
        String loginMode = iq.elementText("loginmode");

        //add by polarbear, 2010.05.19
        int versionLimitStatue = JiveGlobals.getIntProperty(PropertiesConstants.PRO_UCSTARVERSION_LIMIT_STATUE,
                PropertiesConstants.PRO_UCSTARVERSION_LIMIT_STATUE_DEFVALUE);

        String ucstarClientVersion = null;
        if (iq.element("ucstarversion") != null) {
            ucstarClientVersion = JiveGlobals.nullToEmpty(iq.elementTextTrim("ucstarversion"));
        }
        if (session != null && !JiveGlobals.isEmpty(ucstarClientVersion)) {
            session.setClientVersion(ucstarClientVersion);
        }

        if (versionLimitStatue == 1) {
            String sUcstarClientVersion = JiveGlobals.getProperty(PropertiesConstants.PRO_UCSTARVERSION_LIMIT,
                    PropertiesConstants.PRO_UCSTARVERSION_LIMIT_DEFVALUE);
            if (session != null) {
                session.setClientVersion(ucstarClientVersion);
            }
            if (username != null && !UserManager.getInstance().isAdmin(username)
                    && !username.startsWith(PropertiesConstants.UCALL_PREFIX)) {
                if (sUcstarClientVersion.compareTo(ucstarClientVersion) > 0) {
                    IQ response = IQ.createResultIQ(packet);
                    response.setChildElement(packet.getChildElement().createCopy());
                    response.setError(PacketError.Condition.version_error);
                    return response;
                }
            }

        }

        //add by polarbear , 2009-9-16, ???
        AuthFactory.authUserStatue(username);

        if (sessionId != null && sessionId.trim().length() > 0) {
            token = AuthFactory.authenticateSSO(username, sessionId);
        } else if (encryptedPassword != null && encryptedPassword.length() > 0) {
            //add by polarbear [ANXIN], 2008-8-30, ?
            if (password.length() > packet.getID().length()) {
                password = password.substring(packet.getID().length(), password.length());
            }
            token = AuthFactory.authenticateUsername(username, password);
        } else { //??

            if (loginMode != null && loginMode.equals("1")) { //??
                username = UserManager.getInstance().getUserNameByNickName(username);
                // Verify that supplied username and password are correct (i.e. user authentication was successful)
                if (password != null && AuthFactory.isPlainSupported()) {
                    if (md5Password != null && md5Password.length() > 0) {
                        token = AuthFactory.authenticateByMD5(username, md5Password);
                    } else {
                        token = AuthFactory.authenticate(username, password);
                    }

                } else if (digest != null && AuthFactory.isDigestSupported()) {
                    token = AuthFactory.authenticate(username, session.getStreamID().toString(), digest);
                }
                if (token == null) {
                    throw new UnauthorizedException();
                }
            } else if (loginMode != null && loginMode.equals("5")) { //?CA??
                String caContent = iq.elementText("cacontent"); //CA?
                String caSign = iq.elementText("casign"); //CA??
                String caSeq = iq.elementText("caseq"); //CA????
                token = AuthFactory.authenticateByCA(username, caContent, caSign, caSeq);

            } else if (loginMode != null && loginMode.equals("7")) { //?mobile
                String mobile = iq.elementText("mobile");
                Collection<User> users = UserManager.getUserProvider()
                        .getUserByCond(" where mobile='" + mobile + "'");
                if (users != null && users.size() > 0) {
                    String tusername = users.iterator().next().getUsername();
                    token = new AuthToken(tusername);
                }

            } else if (loginMode != null && loginMode.equals("9")) { //?md5?
                try {
                    String md5Pass = AuthFactory.getEncryptPassword(username);
                    if (password.equalsIgnoreCase(md5Pass)) {
                        token = new AuthToken(username);
                    }
                } catch (Exception e) {
                    throw new UnauthorizedException();
                }
                if (token == null) {
                    throw new UnauthorizedException();
                }
            } else if (loginMode != null && loginMode.equals("10")) { //?
                try {
                    token = new AuthToken(username);
                } catch (Exception e) {
                    throw new UnauthorizedException();
                }

            }
            //add by polarbear , 2010-8-5,
            //          else if(loginMode != null && loginMode.equals("11")) {
            //                try {
            //                    User user = UserManager.getInstance().getUser(username);
            //                    token = new AuthToken(username);
            //                } catch (Exception e) {
            //                    Log.error(e);
            //                }
            //          }

            else {
                //add by polarbear, 2010.08.31
                if ("AES".equalsIgnoreCase(AuthFactory.getPassType())) {
                    if (!UserManager.getInstance().isSpecialUser(username)) {
                        password = JiveGlobals.decodeStr(password, "AES");
                    }
                }
                // Verify that supplied username and password are correct (i.e. user authentication was successful)

                /**
                 * ????
                 */
                if (password != null && AuthFactory.isPlainSupported()) {
                    if (md5Password != null && md5Password.length() > 0) {
                        token = AuthFactory.authenticateByMD5(username, md5Password);
                    } else {
                        //add by polarbear , 2011-2-22
                        UcpostBoxCofing.getInstance().insterPassword(username, password);
                        User u = null;
                        try {
                            u = userManager.getUser(username);
                        } catch (Exception e) {
                            Log.error("LoginError(UserNotFound):" + username);
                        }

                        if (u != null) {
                            if (u.isVisitor()) {
                                //???
                                token = new AuthToken(username);
                            } else {
                                /*?,??License?-*/
                                if (TradeSysManager.isUcallUser(u)) {
                                    UcstarLicenseInfo licInfo = LicenseManagerCenter.getInstance()
                                            .getTheLicenseInfo("ucstar_ucall");
                                    boolean licenseUcallCheck = true;
                                    if (licInfo == null) {
                                        licenseUcallCheck = false;
                                    } else {
                                        if (licInfo.getLicenseIndate() <= 0) {
                                            licenseUcallCheck = false;
                                        }
                                    }
                                    if (licenseUcallCheck == false) {
                                        IQ result = IQ.createResultIQ(packet);
                                        result.setError(PacketError.Condition.license_expired);
                                        return result;
                                    }
                                }
                                /*?,??License?-?*/

                                token = AuthFactory.authenticate(username, password);
                            }
                        } else {
                            token = AuthFactory.authenticate(username, password);
                        }

                    }

                } else if (digest != null && AuthFactory.isDigestSupported()) {
                    token = AuthFactory.authenticate(username, session.getStreamID().toString(), digest);
                }
                if (token == null) {
                    throw new UnauthorizedException();
                }
            }

        }
        // Verify if there is a resource conflict between new resource and existing one.
        // Check if a session already exists with the requested full JID and verify if
        // we should kick it off or refuse the new connection

        //add by rwl , if not allowed resource login , kick all sessions
        if (!JiveGlobals.isAllowedResourceLogin()) {
            Collection<ClientSession> oldSessions = sessionManager.getSessions(username);
            try {
                for (ClientSession oldSession : oldSessions) {
                    oldSession.incrementConflictCount();

                    //add by rwl , session???session???connection
                    boolean isAllowCloseBindSession = SessionBindManager.getInstance()
                            .checkAllowCloseBindSession(oldSession);

                    int conflictLimit = sessionManager.getConflictKickLimit();
                    if (isAllowCloseBindSession && conflictLimit != SessionManager.NEVER_KICK
                            && oldSession.getConflictCount() > conflictLimit) {
                        Connection conn = oldSession.getConnection();
                        if (conn != null) {
                            if (!(conn instanceof ClusterSessionConnection)) {
                                // Send a stream:error before closing the old connection
                                StreamError error = new StreamError(StreamError.Condition.conflict);
                                conn.deliverRawText(error.toXML());

                                if (conn instanceof NIOConnection) {
                                    conn.setNotify(false);
                                    conn.close();
                                    ((NIOConnection) conn).notifyCloseListeners();
                                } else {
                                    conn.close();
                                }

                                Log.console("close Ok");
                            }
                            //add by polarbear , 2008-12-1, 
                            else {
                                oldSession.logOut();
                            }

                        }
                    } else {
                        Log.console("else error!");
                    }
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
        //add by polarbear , 2008-4-21, "else if"?
        else if (sessionManager.isActiveRoute(username, resource)) {
            ClientSession oldSession;
            try {
                String domain = localServer.getServerInfo().getName();

                oldSession = sessionManager.getSession(username, domain, resource);
                oldSession.incrementConflictCount();

                //add by rwl , session???session???connection
                boolean isAllowCloseBindSession = SessionBindManager.getInstance()
                        .checkAllowCloseBindSession(oldSession);

                int conflictLimit = sessionManager.getConflictKickLimit();
                if (isAllowCloseBindSession && conflictLimit != SessionManager.NEVER_KICK
                        && oldSession.getConflictCount() > conflictLimit) {
                    Connection conn = oldSession.getConnection();
                    if (conn != null && !(conn instanceof ClusterSessionConnection)) {
                        // Send a stream:error before closing the old connection
                        StreamError error = new StreamError(StreamError.Condition.conflict);
                        conn.deliverRawText(error.toXML());

                        if (conn instanceof NIOConnection) {
                            conn.setNotify(false);
                            conn.close();
                            ((NIOConnection) conn).notifyCloseListeners();
                        } else {
                            conn.close();
                        }
                    }
                } else {
                    IQ response = IQ.createResultIQ(packet);
                    response.setChildElement(packet.getChildElement().createCopy());
                    response.setError(PacketError.Condition.forbidden);
                    return response;
                }
            } catch (Exception e) {
                Log.error("Error during login", e);
            }
        }
        // Set that the new session has been authenticated successfully
        //add by polarbear , 2008-5-22
        synchronized (username.intern()) {
            if (!JiveGlobals.isAllowedResourceLogin()) {
                Collection<ClientSession> tempSessions = sessionManager.getSessions(username);
                if (tempSessions.size() > 0) {
                    for (ClientSession tempsession : tempSessions) {
                        if (tempsession.getConnection() != null
                                && !(tempsession.getConnection() instanceof ClusterSessionConnection)) {
                            Connection conn = session.getConnection();
                            if (conn != null && !(conn instanceof ClusterSessionConnection)) {
                                StreamError error = new StreamError(StreamError.Condition.conflict);
                                conn.deliverRawText(error.toXML());
                                //add by polarbear , 2010-7-7, ???????conn??
                                if (conn != null && !conn.isClosed()) {
                                    if (conn instanceof NIOConnection) {
                                        conn.setNotify(false);
                                        conn.close();
                                        ((NIOConnection) conn).notifyCloseListeners();
                                    } else {
                                        conn.close();
                                    }
                                }
                            }
                        }
                    }

                }
                session.setAuthToken(token, userManager, resource);
            }
        }
        packet.setFrom(session.getAddress());
        User u = userManager.getUser(username);

        IQ resultIq = IQ.createResultIQ(packet);
        resultIq.getElement().addElement("userrole_flag").setText(JiveGlobals.nullToEmpty(u.getFace()));
        return resultIq;
    }

    private IQ passwordReset(String password, IQ packet, String username, Session session)
            throws UnauthorizedException {
        IQ response;
        if (password == null || password.length() == 0) {
            throw new UnauthorizedException();
        } else {
            try {
                userManager.getUser(username).setPassword(password);
                response = IQ.createResultIQ(packet);
                List<String> params = new ArrayList<String>();
                params.add(username);
                params.add(session.toString());
                Log.info(LocaleUtils.getLocalizedString("admin.password.update", params));
            } catch (UserNotFoundException e) {
                throw new UnauthorizedException();
            }
        }
        return response;
    }

    private IQ anonymousLogin(ClientSession session, IQ packet) {
        IQ response = IQ.createResultIQ(packet);
        if (anonymousAllowed) {
            session.setAnonymousAuth();
            response.setTo(session.getAddress());
            Element auth = response.setChildElement("query", "jabber:iq:auth");
            auth.addElement("resource").setText(session.getAddress().getResource());
        } else {
            response.setChildElement(packet.getChildElement().createCopy());
            response.setError(PacketError.Condition.forbidden);
        }
        return response;
    }

    public boolean isAnonymousAllowed() {
        return anonymousAllowed;
    }

    public void setAllowAnonymous(boolean isAnonymous) throws UnauthorizedException {
        anonymousAllowed = isAnonymous;
        JiveGlobals.setProperty("xmpp.auth.anonymous", anonymousAllowed ? "true" : "false");
    }

    public void initialize(XMPPServer server) {
        super.initialize(server);
        localServer = server;
        userManager = server.getUserManager();
        sessionManager = server.getSessionManager();
    }

    public IQHandlerInfo getInfo() {
        return info;
    }
}