149 lines
6.2 KiB
Java
149 lines
6.2 KiB
Java
/*
|
|
* DavMail POP/IMAP/SMTP/CalDav/LDAP Exchange Gateway
|
|
* Copyright (C) 2012 Mickael Guessant
|
|
*
|
|
* This program is free software; you can redistribute it and/or
|
|
* modify it under the terms of the GNU General Public License
|
|
* as published by the Free Software Foundation; either version 2
|
|
* of the License, or (at your option) any later version.
|
|
*
|
|
* This program is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
* GNU General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU General Public License
|
|
* along with this program; if not, write to the Free Software
|
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
|
*/
|
|
package davmail.http;
|
|
|
|
import davmail.Settings;
|
|
import org.apache.log4j.Logger;
|
|
import org.ietf.jgss.*;
|
|
|
|
import javax.security.auth.Subject;
|
|
import javax.security.auth.callback.*;
|
|
import javax.security.auth.login.LoginContext;
|
|
import javax.security.auth.login.LoginException;
|
|
import java.awt.GraphicsEnvironment;
|
|
import java.io.BufferedReader;
|
|
import java.io.IOException;
|
|
import java.io.InputStreamReader;
|
|
import java.security.PrivilegedAction;
|
|
import java.security.Security;
|
|
|
|
|
|
/**
|
|
* Kerberos helper class.
|
|
*/
|
|
public class KerberosHelper {
|
|
protected static final Logger LOGGER = Logger.getLogger(KerberosHelper.class);
|
|
protected static final Object LOCK = new Object();
|
|
protected static KerberosCallbackHandler kerberosCallbackHandler;
|
|
protected static LoginContext loginContext;
|
|
|
|
static {
|
|
Security.setProperty("login.configuration.provider", "davmail.http.KerberosLoginConfiguration");
|
|
kerberosCallbackHandler = new KerberosCallbackHandler();
|
|
}
|
|
|
|
protected static class KerberosCallbackHandler implements CallbackHandler {
|
|
String principal;
|
|
String password;
|
|
|
|
protected KerberosCallbackHandler() {
|
|
}
|
|
|
|
protected KerberosCallbackHandler(String principal, String password) {
|
|
this.principal = principal;
|
|
this.password = password;
|
|
}
|
|
|
|
public void handle(Callback[] callbacks) throws IOException, UnsupportedCallbackException {
|
|
for (int i = 0; i < callbacks.length; i++) {
|
|
if (callbacks[i] instanceof NameCallback) {
|
|
if (principal == null) {
|
|
// if we get there kerberos token is missing or invalid
|
|
if (Settings.getBooleanProperty("davmail.server") || GraphicsEnvironment.isHeadless()) {
|
|
// headless or server mode
|
|
System.out.print(((NameCallback) callbacks[i]).getPrompt());
|
|
BufferedReader inReader = new BufferedReader(new InputStreamReader(System.in));
|
|
principal = inReader.readLine();
|
|
} else {
|
|
// TODO: get username and password from dialog
|
|
}
|
|
}
|
|
final NameCallback nameCallback = (NameCallback) callbacks[i];
|
|
nameCallback.setName(principal);
|
|
} else if (callbacks[i] instanceof PasswordCallback) {
|
|
if (password == null) {
|
|
// if we get there kerberos token is missing or invalid
|
|
if (Settings.getBooleanProperty("davmail.server") || GraphicsEnvironment.isHeadless()) {
|
|
// headless or server mode
|
|
System.out.print(((PasswordCallback) callbacks[i]).getPrompt());
|
|
BufferedReader inReader = new BufferedReader(new InputStreamReader(System.in));
|
|
password = inReader.readLine();
|
|
}
|
|
}
|
|
final PasswordCallback passCallback = (PasswordCallback) callbacks[i];
|
|
passCallback.setPassword(password.toCharArray());
|
|
} else {
|
|
throw new UnsupportedCallbackException(callbacks[i]);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
public static byte[] getToken(final String host, final byte[] token) throws GSSException, LoginException {
|
|
LOGGER.debug("KerberosHelper.getToken " + host + " " + token.length + " bytes token");
|
|
|
|
LoginContext loginContext = login();
|
|
|
|
Object result = Subject.doAs(loginContext.getSubject(), new PrivilegedAction() {
|
|
|
|
public Object run() {
|
|
Object result;
|
|
try {
|
|
GSSManager manager = GSSManager.getInstance();
|
|
GSSName serverName = manager.createName("HTTP/" + host, null);
|
|
// Kerberos v5 OID
|
|
Oid krb5Oid = new Oid("1.2.840.113554.1.2.2");
|
|
|
|
GSSContext context = manager.createContext(serverName, krb5Oid, null,
|
|
GSSContext.DEFAULT_LIFETIME);
|
|
|
|
//context.requestMutualAuth(true);
|
|
context.requestCredDeleg(true);
|
|
|
|
result = context.initSecContext(token, 0, token.length);
|
|
} catch (GSSException e) {
|
|
result = e;
|
|
}
|
|
return result;
|
|
}
|
|
});
|
|
if (result instanceof GSSException) {
|
|
throw (GSSException) result;
|
|
}
|
|
|
|
LOGGER.debug("KerberosHelper.getToken return " + ((byte[]) result).length + " bytes token");
|
|
return (byte[]) result;
|
|
}
|
|
|
|
public static void setCredentials(String principal, String password) {
|
|
kerberosCallbackHandler = new KerberosCallbackHandler(principal, password);
|
|
}
|
|
|
|
public static LoginContext login() throws LoginException {
|
|
synchronized (LOCK) {
|
|
if (loginContext == null) {
|
|
final LoginContext localLoginContext = new LoginContext("spnego-client", kerberosCallbackHandler);
|
|
localLoginContext.login();
|
|
loginContext = localLoginContext;
|
|
}
|
|
}
|
|
return loginContext;
|
|
}
|
|
}
|