/*
* NOTE: This copyright does *not* cover user programs that use HQ
* program services by normal system calls through the application
* program interfaces provided as part of the Hyperic Plug-in Development
* Kit or the Hyperic Client Development Kit - this is merely considered
* normal use of the program, and does *not* fall under the heading of
* "derived work".
*
* Copyright (C) [2004, 2005, 2006], Hyperic, Inc.
* This file is part of HQ.
*
* HQ is free software; you can redistribute it and/or modify
* it under the terms version 2 of the GNU General Public License as
* published by the Free Software Foundation. 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307
* USA.
*/
package org.hyperic.hq.plugin.weblogic;
import java.io.IOException;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
import java.util.Properties;
import java.security.PrivilegedAction;
import javax.security.auth.Subject;
import javax.security.auth.callback.Callback;
import javax.security.auth.callback.CallbackHandler;
import javax.security.auth.callback.NameCallback;
import javax.security.auth.callback.PasswordCallback;
import javax.security.auth.callback.TextOutputCallback;
import javax.security.auth.callback.UnsupportedCallbackException;
import javax.security.auth.login.LoginContext;
import javax.security.auth.login.LoginException;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import weblogic.security.Security;
import weblogic.security.auth.callback.URLCallback;
import org.hyperic.hq.product.Metric;
import org.hyperic.util.timer.StopWatch;
/**
* Helper for JAAS support.
*/
public class WeblogicAuth
implements CallbackHandler {
private static Map handlers =
Collections.synchronizedMap(new HashMap());
//see agent/jaas.properties
private static final String LOGIN_MODULE = "org.hyperic.hq.weblogic";
private static Log log = LogFactory.getLog(WeblogicAuth.class);
private LoginContext loginContext = null;
private Subject subject = null;
private String url;
private String username;
private char[] passwordArray;
private WeblogicAuth() { }
public static WeblogicAuth getInstance(Metric metric) {
return getInstance(metric.getProperties());
}
public static void clearCache() {
handlers.clear();
}
public static WeblogicAuth getInstance(Properties props) {
String url =
props.getProperty(WeblogicMetric.PROP_ADMIN_URL, "");
String username =
props.getProperty(WeblogicMetric.PROP_ADMIN_USERNAME, "");
String password =
props.getProperty(WeblogicMetric.PROP_ADMIN_PASSWORD, "");
return getInstance(url, username, password);
}
public static WeblogicAuth getInstance(String url,
String username,
String password) {
int hash = 0;
hash ^= url.hashCode();
hash ^= username.hashCode();
hash ^= password.hashCode();
Integer key = new Integer(hash);
WeblogicAuth auth = (WeblogicAuth)handlers.get(key);
if (auth == null) {
auth = new WeblogicAuth();
handlers.put(key, auth);
auth.url = url;
auth.username = username;
auth.passwordArray = password.toCharArray();
}
return auth;
}
public Object runAs(PrivilegedAction action)
throws SecurityException {
return Security.runAs(getSubject(), action);
}
public Subject getSubject()
throws SecurityException {
if (this.subject != null) {
return this.subject;
}
StopWatch timer = null;
if (this.loginContext == null) {
if (log.isDebugEnabled()) {
timer = new StopWatch();
}
try {
this.loginContext = new LoginContext(LOGIN_MODULE, this);
this.loginContext.login();
} catch (LoginException e) {
//e.printStackTrace();
this.loginContext = null;
throw new SecurityException(e.getMessage());
}
}
this.subject = this.loginContext.getSubject();
if (timer != null) {
log.debug(this.url + " login took: " + timer);
}
if (this.subject == null) {
throw new SecurityException("Authentication failed: reason unknown.");
}
return this.subject;
}
public void handle(Callback[] callbacks)
throws IOException, UnsupportedCallbackException {
for (int i = 0; i < callbacks.length; i++) {
if (callbacks[i] instanceof TextOutputCallback) {
TextOutputCallback toc = (TextOutputCallback)callbacks[i];
switch (toc.getMessageType()) {
case TextOutputCallback.INFORMATION:
log.info(toc.getMessage());
break;
case TextOutputCallback.ERROR:
log.error(toc.getMessage());
break;
case TextOutputCallback.WARNING:
log.warn(toc.getMessage());
break;
default:
throw new IOException("Unsupported message type: " +
toc.getMessageType());
}
}
else if (callbacks[i] instanceof NameCallback) {
NameCallback nc = (NameCallback)callbacks[i];
nc.setName(this.username);
}
else if (callbacks[i] instanceof URLCallback) {
URLCallback uc = (URLCallback)callbacks[i];
uc.setURL(this.url);
}
else if (callbacks[i] instanceof PasswordCallback) {
PasswordCallback pc = (PasswordCallback)callbacks[i];
pc.setPassword(this.passwordArray);
}
else {
throw new UnsupportedCallbackException(callbacks[i],
"Unrecognized Callback");
}
}
}
}