package nl.topicus.konijn.xmpp.authentication; import nl.topicus.konijn.xmpp.util.WicketInjector; import org.apache.commons.codec.binary.Base64; import org.apache.vysper.xmpp.addressing.EntityFormatException; import org.apache.vysper.xmpp.addressing.EntityImpl; import org.apache.vysper.xmpp.authentication.AuthenticationResponses; import org.apache.vysper.xmpp.modules.core.sasl.handler.AbstractSASLHandler; import org.apache.vysper.xmpp.protocol.ResponseStanzaContainer; import org.apache.vysper.xmpp.protocol.ResponseStanzaContainerImpl; import org.apache.vysper.xmpp.protocol.SessionStateHolder; import org.apache.vysper.xmpp.server.SessionContext; import org.apache.vysper.xmpp.server.SessionState; import org.apache.vysper.xmpp.stanza.Stanza; /** * Response Handler for MD5-Digest authentication * * @author Joost Limburg */ public class ResponseHandler extends AbstractSASLHandler { private static final AuthenticationResponses AUTHENTICATION_RESPONSES = new AuthenticationResponses(); public String getName() { return "response"; } public boolean isSessionRequired() { return true; } @Override protected ResponseStanzaContainer executeWorker(Stanza stanza, SessionContext sessionContext, SessionStateHolder sessionStateHolder) { Stanza curStanza = AUTHENTICATION_RESPONSES .getFailureMalformedRequest(); try { WicketInjector.inject(sessionContext); if (sessionContext.getAttribute("nonce") != null) { String nonce = (String) sessionContext.getAttribute("nonce"); byte decoded[] = Base64.decodeBase64(stanza.getInnerText() .getText()); String decodedString = new String(decoded); boolean passwordSet = false; boolean usernameSet = false; boolean nonceMatches = false; boolean cnonceSet = false; // Disect text: for (String key : decodedString.split(",")) { String disected[] = key.split("="); if (disected.length == 2 && disected[1].length() > 0) { String valued = disected[1].replace("\"", ""); if (disected[0].equalsIgnoreCase("username")) { usernameSet = true; sessionContext.putAttribute("username", valued); } else if (disected[0].equalsIgnoreCase("nonce")) { nonceMatches = valued.equals(nonce); } else if (disected[0].equalsIgnoreCase("cnonce")) { sessionContext.putAttribute("cnonce", valued); cnonceSet = true; } else if (disected[0].equalsIgnoreCase("response")) { passwordSet = true; sessionContext.putAttribute("password", valued); } } } // Check for success: if (passwordSet && usernameSet && nonceMatches && cnonceSet) { EntityImpl initiatingEntity; try { initiatingEntity = EntityImpl .parse((String) sessionContext .getAttribute("username") + "@" + sessionContext.getServerJID() .getDomain()); boolean authorized = sessionContext .getServerRuntimeContext() .getUserAuthentication() .verifyCredentials( initiatingEntity, (String) sessionContext .getAttribute("password"), sessionContext); // Verify password: if (authorized) { sessionContext .setInitiatingEntity(initiatingEntity); sessionStateHolder .setState(SessionState.AUTHENTICATED); curStanza = AUTHENTICATION_RESPONSES.getSuccess(); } else { curStanza = AUTHENTICATION_RESPONSES .getFailureNotAuthorized(); } } catch (EntityFormatException e) { } } else { curStanza = AUTHENTICATION_RESPONSES .getFailureNotAuthorized(); } } } catch (Exception ex) { ex.printStackTrace(); } return new ResponseStanzaContainerImpl(curStanza); } }