1 11 12 package org.jivesoftware.messenger.handler; 13 14 import org.dom4j.DocumentHelper; 15 import org.dom4j.Element; 16 import org.dom4j.QName; 17 import org.jivesoftware.messenger.*; 18 import org.jivesoftware.messenger.auth.AuthFactory; 19 import org.jivesoftware.messenger.auth.AuthToken; 20 import org.jivesoftware.messenger.auth.UnauthorizedException; 21 import org.jivesoftware.messenger.user.UserManager; 22 import org.jivesoftware.messenger.user.UserNotFoundException; 23 import org.jivesoftware.util.LocaleUtils; 24 import org.jivesoftware.util.Log; 25 import org.jivesoftware.util.JiveGlobals; 26 import org.jivesoftware.stringprep.Stringprep; 27 import org.jivesoftware.stringprep.StringprepException; 28 import org.xmpp.packet.IQ; 29 import org.xmpp.packet.JID; 30 import org.xmpp.packet.PacketError; 31 import org.xmpp.packet.StreamError; 32 33 import java.util.ArrayList ; 34 import java.util.List ; 35 36 55 public class IQAuthHandler extends IQHandler implements IQAuthInfo { 56 57 private static boolean anonymousAllowed; 58 59 private Element probeResponse; 60 private IQHandlerInfo info; 61 62 private UserManager userManager; 63 private XMPPServer localServer; 64 private SessionManager sessionManager; 65 66 69 public IQAuthHandler() { 70 super("XMPP Authentication handler"); 71 info = new IQHandlerInfo("query", "jabber:iq:auth"); 72 73 probeResponse = DocumentHelper.createElement(QName.get("query", "jabber:iq:auth")); 74 probeResponse.addElement("username"); 75 if (AuthFactory.isPlainSupported()) { 76 probeResponse.addElement("password"); 77 } 78 if (AuthFactory.isDigestSupported()) { 79 probeResponse.addElement("digest"); 80 } 81 probeResponse.addElement("resource"); 82 anonymousAllowed = "true".equals(JiveGlobals.getProperty("xmpp.auth.anonymous")); 83 } 84 85 public IQ handleIQ(IQ packet) throws UnauthorizedException, PacketException { 86 try { 87 ClientSession session = sessionManager.getSession(packet.getFrom()); 88 if (session == null) { 90 Log.error("Error during authentication. Session not found in " + 91 sessionManager.getPreAuthenticatedKeys() + 92 " for key " + 93 packet.getFrom()); 94 IQ reply = IQ.createResultIQ(packet); 96 reply.setChildElement(packet.getChildElement().createCopy()); 97 reply.setError(PacketError.Condition.internal_server_error); 98 return reply; 99 } 100 IQ response = null; 101 try { 102 Element iq = packet.getElement(); 103 Element query = iq.element("query"); 104 Element queryResponse = probeResponse.createCopy(); 105 if (IQ.Type.get == packet.getType()) { 106 String username = query.elementTextTrim("username"); 107 if (username != null) { 108 queryResponse.element("username").setText(username); 109 } 110 response = IQ.createResultIQ(packet); 111 response.setChildElement(queryResponse); 112 if (session.getStatus() != Session.STATUS_AUTHENTICATED) { 117 response.setTo((JID)null); 118 } 119 } 120 else { 122 if (query.elements().isEmpty()) { 123 response = anonymousLogin(session, packet); 125 } 126 else { 127 String username = query.elementTextTrim("username"); 128 String password = query.elementTextTrim("password"); 130 String digest = null; 131 if (query.element("digest") != null) { 132 digest = query.elementTextTrim("digest").toLowerCase(); 133 } 134 135 if (session.getStatus() == Session.STATUS_AUTHENTICATED) { 137 response = passwordReset(password, packet, username, session); 138 } 139 else { 140 response = 142 login(username, query, packet, response, password, session, 143 digest); 144 } 145 } 146 } 147 } 148 catch (UserNotFoundException e) { 149 response = IQ.createResultIQ(packet); 150 response.setChildElement(packet.getChildElement().createCopy()); 151 response.setError(PacketError.Condition.not_authorized); 152 } 153 catch (UnauthorizedException e) { 154 response = IQ.createResultIQ(packet); 155 response.setChildElement(packet.getChildElement().createCopy()); 156 response.setError(PacketError.Condition.not_authorized); 157 } 158 session.process(response); 162 } 163 catch (Exception e) { 164 Log.error("Error handling authentication IQ packet", e); 165 } 166 return null; 167 } 168 169 private IQ login(String username, Element iq, IQ packet, IQ response, String password, 170 ClientSession session, String digest) throws UnauthorizedException, 171 UserNotFoundException 172 { 173 String resource = iq.elementTextTrim("resource"); 174 if (resource != null) { 175 try { 176 resource = Stringprep.resourceprep(resource); 177 } 178 catch (StringprepException e) { 179 throw new IllegalArgumentException ("Invalid resource: " + resource); 180 } 181 } 182 else { 183 response = IQ.createResultIQ(packet); 185 response.setChildElement(packet.getChildElement().createCopy()); 186 response.setError(PacketError.Condition.not_acceptable); 187 } 188 189 if (sessionManager.isActiveRoute(username, resource)) { 192 ClientSession oldSession = null; 193 try { 194 String domain = localServer.getServerInfo().getName(); 195 oldSession = sessionManager.getSession(username, domain, resource); 196 oldSession.incrementConflictCount(); 197 int conflictLimit = sessionManager.getConflictKickLimit(); 198 if (conflictLimit != SessionManager.NEVER_KICK && oldSession.getConflictCount() > conflictLimit) { 199 Connection conn = oldSession.getConnection(); 200 if (conn != null) { 201 StreamError error = new StreamError(StreamError.Condition.conflict); 203 conn.getWriter().write(error.toXML()); 204 conn.close(); 205 } 206 } 207 else { 208 response = IQ.createResultIQ(packet); 209 response.setChildElement(packet.getChildElement().createCopy()); 210 response.setError(PacketError.Condition.forbidden); 211 } 212 } 213 catch (Exception e) { 214 Log.error("Error during login", e); 215 } 216 } 217 if (response == null) { 219 AuthToken token = null; 220 if (password != null && AuthFactory.isPlainSupported()) { 221 token = AuthFactory.authenticate(username, password); 222 } 223 else if (digest != null && AuthFactory.isDigestSupported()) { 224 token = AuthFactory.authenticate(username, session.getStreamID().toString(), 225 digest); 226 } 227 if (token == null) { 228 throw new UnauthorizedException(); 229 } 230 else { 231 session.setAuthToken(token, userManager, resource); 232 packet.setFrom(session.getAddress()); 233 response = IQ.createResultIQ(packet); 234 } 235 } 236 return response; 237 } 238 239 private IQ passwordReset(String password, IQ packet, String username, Session session) 240 throws UnauthorizedException 241 { 242 IQ response; 243 if (password == null || password.length() == 0) { 244 throw new UnauthorizedException(); 245 } 246 else { 247 try { 248 userManager.getUser(username).setPassword(password); 249 response = IQ.createResultIQ(packet); 250 List params = new ArrayList (); 251 params.add(username); 252 params.add(session.toString()); 253 Log.info(LocaleUtils.getLocalizedString("admin.password.update", params)); 254 } 255 catch (UserNotFoundException e) { 256 throw new UnauthorizedException(); 257 } 258 } 259 return response; 260 } 261 262 private IQ anonymousLogin(ClientSession session, IQ packet) { 263 IQ response = IQ.createResultIQ(packet);; 264 if (anonymousAllowed) { 265 session.setAnonymousAuth(); 266 Element auth = response.setChildElement("query", "jabber:iq:auth"); 267 auth.addElement("resource").setText(session.getAddress().getResource()); 268 } 269 else { 270 response.setChildElement(packet.getChildElement().createCopy()); 271 response.setError(PacketError.Condition.forbidden); 272 } 273 return response; 274 } 275 276 public boolean isAllowAnonymous() { 277 return anonymousAllowed; 278 } 279 280 public void setAllowAnonymous(boolean isAnonymous) throws UnauthorizedException { 281 anonymousAllowed = isAnonymous; 282 JiveGlobals.setProperty("xmpp.auth.anonymous", anonymousAllowed ? "true" : "false"); 283 } 284 285 public void initialize(XMPPServer server) { 286 super.initialize(server); 287 localServer = server; 288 userManager = server.getUserManager(); 289 sessionManager = server.getSessionManager(); 290 } 291 292 public IQHandlerInfo getInfo() { 293 return info; 294 } 295 } | Popular Tags |