001 /**
002 * Licensed to the Apache Software Foundation (ASF) under one or more
003 * contributor license agreements. See the NOTICE file distributed with
004 * this work for additional information regarding copyright ownership.
005 * The ASF licenses this file to You under the Apache License, Version 2.0
006 * (the "License"); you may not use this file except in compliance with
007 * the License. You may obtain a copy of the License at
008 *
009 * http://www.apache.org/licenses/LICENSE-2.0
010 *
011 * Unless required by applicable law or agreed to in writing, software
012 * distributed under the License is distributed on an "AS IS" BASIS,
013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014 * See the License for the specific language governing permissions and
015 * limitations under the License.
016 */
017
018 package org.apache.geronimo.javamail.authentication;
019
020 import java.lang.reflect.Constructor;
021 import java.util.List;
022 import java.util.Properties;
023
024 import org.apache.geronimo.javamail.util.ProtocolProperties;
025
026 public class AuthenticatorFactory {
027 // the list of authentication mechanisms we have direct support for. Others come from
028 // SASL, if it's available.
029
030 public static final String AUTHENTICATION_PLAIN = "PLAIN";
031 public static final String AUTHENTICATION_LOGIN = "LOGIN";
032 public static final String AUTHENTICATION_CRAMMD5 = "CRAM-MD5";
033 public static final String AUTHENTICATION_DIGESTMD5 = "DIGEST-MD5";
034
035 static public ClientAuthenticator getAuthenticator(ProtocolProperties props, List mechanisms, String host, String username, String password, String authId, String realm)
036 {
037 // if the authorization id isn't given, then this is the same as the logged in user name.
038 if (authId == null) {
039 authId = username;
040 }
041
042 // if SASL is enabled, try getting a SASL authenticator first
043 if (props.getBooleanProperty("sasl.enable", false)) {
044 // we need to convert the mechanisms map into an array of strings for SASL.
045 String [] mechs = (String [])mechanisms.toArray(new String[mechanisms.size()]);
046
047 try {
048 // need to try to load this using reflection since it has references to
049 // the SASL API. That's only available with 1.5 or later.
050 Class authenticatorClass = Class.forName("org.apache.geronimo.javamal.authentication.SASLAuthenticator");
051 Constructor c = authenticatorClass.getConstructor(new Class[] {
052 (new String[0]).getClass(),
053 Properties.class,
054 String.class,
055 String.class,
056 String.class,
057 String.class,
058 String.class,
059 String.class
060 });
061
062 Object[] args = { mechs, props.getProperties(), props.getProtocol(), host, realm, authId, username, password };
063
064 return (ClientAuthenticator)c.newInstance(args);
065 } catch (Throwable e) {
066 // Any exception is likely because we're running on 1.4 and can't use the Sasl API.
067 // just ignore and use our fallback implementations.
068 }
069 }
070
071 // now go through the progression of mechanisms we support, from the
072 // most secure to the least secure.
073
074 if (mechanisms.contains(AUTHENTICATION_DIGESTMD5)) {
075 return new DigestMD5Authenticator(host, username, password, realm);
076 } else if (mechanisms.contains(AUTHENTICATION_CRAMMD5)) {
077 return new CramMD5Authenticator(username, password);
078 } else if (mechanisms.contains(AUTHENTICATION_LOGIN)) {
079 return new LoginAuthenticator(username, password);
080 } else if (mechanisms.contains(AUTHENTICATION_PLAIN)) {
081 return new PlainAuthenticator(username, password);
082 } else {
083 // can't find a mechanism we support in common
084 return null;
085 }
086 }
087 }
088