package org.tiki.tikitoken; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import javax.security.auth.callback.CallbackHandler; import javax.security.sasl.Sasl; import javax.security.sasl.SaslException; import javax.security.sasl.SaslServer; import javax.security.sasl.SaslServerFactory; import java.util.HashSet; import java.util.Map; import java.util.Set; /** * A SaslServerFactory implementation that is used to instantiate TikiToken-based SaslServer instances. * * This implementation makes use of a Tiki server for token validation. * * @author Guus der Kinderen, guus@goodbytes.nl */ public class TikiTokenSaslServerFactory implements SaslServerFactory { private static final Logger Log = LoggerFactory.getLogger( TikiTokenSaslServerFactory.class ); public TikiTokenSaslServerFactory() { } public SaslServer createSaslServer( String mechanism, String protocol, String serverName, Map<String, ?> props, CallbackHandler cbh ) throws SaslException { // Do not return an instance when the provided properties contain Policy settings that disallow our implementations. final Set<String> mechanismNames = getMechanismNamesSet( props ); if ( mechanismNames.contains( mechanism ) && mechanism.equalsIgnoreCase( TikiTokenSaslServer.MECHANISM_NAME ) ) { Log.debug( "Instantiating a new TikiTokenSaslServer instance." ); return new TikiTokenSaslServer(); } Log.debug( "Unable to instantiate a SaslServer instance that matches the requested properties." ); return null; } public String[] getMechanismNames( Map<String, ?> props ) { final Set<String> result = getMechanismNamesSet( props ); return result.toArray( new String[ result.size() ] ); } protected final Set<String> getMechanismNamesSet( Map<String, ?> props ) { final Set<String> supportedMechanisms = new HashSet<String>(); supportedMechanisms.add( TikiTokenSaslServer.MECHANISM_NAME ); if ( props != null ) { for ( Map.Entry<String, ?> prop : props.entrySet() ) { if ( !( prop.getValue() instanceof String ) ) { continue; } final String name = prop.getKey(); final String value = (String) prop.getValue(); if ( Sasl.POLICY_NOPLAINTEXT.equalsIgnoreCase( name ) && "true".equalsIgnoreCase( value ) ) { Log.info( "Removing '{}' mechanism, as the provided properties define a NOPLAINTEXT policy.", TikiTokenSaslServer.MECHANISM_NAME ); supportedMechanisms.remove( TikiTokenSaslServer.MECHANISM_NAME ); } // TODO Determine if other policies are relevant. } } return supportedMechanisms; } }