private SASLMechanism selectMechanism() { // Locate the SASLMechanism to use SASLMechanism selectedMechanism = null; Iterator<SASLMechanism> it = REGISTERED_MECHANISMS.iterator(); // Iterate in SASL Priority order over registered mechanisms while (it.hasNext()) { SASLMechanism mechanism = it.next(); String mechanismName = mechanism.getName(); synchronized (BLACKLISTED_MECHANISMS) { if (BLACKLISTED_MECHANISMS.contains(mechanismName)) { continue; } } if (serverMechanisms().contains(mechanismName)) { // Create a new instance of the SASLMechanism for every authentication attempt. selectedMechanism = mechanism.instanceForAuthentication(connection); break; } } return selectedMechanism; }
/** * Registers a new SASL mechanism * * @param mechanism a SASLMechanism subclass. */ public static void registerSASLMechanism(SASLMechanism mechanism) { synchronized (REGISTERED_MECHANISMS) { REGISTERED_MECHANISMS.add(mechanism); Collections.sort(REGISTERED_MECHANISMS); } }
/** * Returns the registered SASLMechanism sorted by the level of preference. * * @return the registered SASLMechanism sorted by the level of preference. */ public static Map<String, String> getRegisterdSASLMechanisms() { Map<String, String> answer = new HashMap<String, String>(); synchronized (REGISTERED_MECHANISMS) { for (SASLMechanism mechanism : REGISTERED_MECHANISMS) { answer.put(mechanism.getClass().getName(), mechanism.getName()); } } return answer; }
/** * Unregister a SASLMechanism by it's full class name. For example * "org.jivesoftware.smack.sasl.javax.SASLCramMD5Mechanism". * * @param clazz the SASLMechanism class's name * @return true if the given SASLMechanism was removed, false otherwise */ public static boolean unregisterSASLMechanism(String clazz) { synchronized (REGISTERED_MECHANISMS) { Iterator<SASLMechanism> it = REGISTERED_MECHANISMS.iterator(); while (it.hasNext()) { SASLMechanism mechanism = it.next(); if (mechanism.getClass().getName().equals(clazz)) { it.remove(); return true; } } } return false; }
/** * Performs SASL authentication of the specified user. If SASL authentication was successful * then resource binding and session establishment will be performed. This method will return * the full JID provided by the server while binding a resource to the connection.<p> * * The server may assign a full JID with a username or resource different than the requested * by this method. * * @param resource the desired resource. * @param cbh the CallbackHandler used to get information from the user * @throws IOException * @throws XMPPErrorException * @throws SASLErrorException * @throws SmackException */ public void authenticate(String resource, CallbackHandler cbh) throws IOException, XMPPErrorException, SASLErrorException, SmackException { SASLMechanism selectedMechanism = selectMechanism(); if (selectedMechanism != null) { currentMechanism = selectedMechanism; synchronized (this) { currentMechanism.authenticate(connection.getHost(), connection.getServiceName(), cbh); try { // Wait until SASL negotiation finishes wait(connection.getPacketReplyTimeout()); } catch (InterruptedException e) { // Ignore } } maybeThrowException(); if (!authenticationSuccessful) { throw NoResponseException.newWith(connection); } } else { throw new SmackException( "SASL Authentication failed. No known authentication mechanisims."); } }
/** * Performs SASL authentication of the specified user. If SASL authentication was successful * then resource binding and session establishment will be performed. This method will return * the full JID provided by the server while binding a resource to the connection.<p> * * The server may assign a full JID with a username or resource different than the requested * by this method. * * @param username the username that is authenticating with the server. * @param password the password to send to the server. * @param resource the desired resource. * @throws XMPPErrorException * @throws SASLErrorException * @throws IOException * @throws SmackException */ public void authenticate(String username, String password, String resource) throws XMPPErrorException, SASLErrorException, IOException, SmackException { SASLMechanism selectedMechanism = selectMechanism(); if (selectedMechanism != null) { currentMechanism = selectedMechanism; synchronized (this) { currentMechanism.authenticate(username, connection.getHost(), connection.getServiceName(), password); try { // Wait until SASL negotiation finishes wait(connection.getPacketReplyTimeout()); } catch (InterruptedException e) { // Ignore } } maybeThrowException(); if (!authenticationSuccessful) { throw NoResponseException.newWith(connection); } } else { throw new SmackException( "SASL Authentication failed. No known authentication mechanisims."); } }
/** * Returns the registerd SASLMechanism classes sorted by the level of * preference. * * @return the registerd SASLMechanism classes sorted by the level of * preference. */ public static List<Class<? extends SASLMechanism>> getRegisterSASLMechanisms() { List<Class<? extends SASLMechanism>> answer = new ArrayList<Class<? extends SASLMechanism>>(); for (String mechanismsPreference : mechanismsPreferences) { answer.add(implementedMechanisms.get(mechanismsPreference)); } return answer; }
@Override protected SASLMechanism newInstance() { return new SASLExternalMechanism(); }
/** * Registers a new SASL mechanism * * @param name * common name of the SASL mechanism. E.g.: PLAIN, DIGEST-MD5 or * KERBEROS_V4. * @param mClass * a SASLMechanism subclass. */ public static void registerSASLMechanism(String name, Class<? extends SASLMechanism> mClass) { implementedMechanisms.put(name, mClass); }