User: oleg
Date: 00/10/16 11:00:19
Added: src/main/org/jboss/security ClientLoginModule.java
JaasSecurityManager.java
JaasSecurityManagerService.java
JaasSecurityManagerServiceMBean.java
SimpleServerLoginModule.java
Log:
JAAS-based security is initiated
Revision Changes Path
1.1 jboss/src/main/org/jboss/security/ClientLoginModule.java
Index: ClientLoginModule.java
===================================================================
/*
* jBoss, the OpenSource EJB server
*
* Distributable under GPL license.
* See terms of license at gnu.org.
*/
package org.jboss.security;
import java.util.Map;
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.UnsupportedCallbackException;
import javax.security.auth.login.LoginException;
import javax.security.auth.spi.LoginModule;
import org.jboss.system.SecurityAssociation;
import org.jboss.system.SimplePrincipal;
public class ClientLoginModule implements LoginModule {
private Subject _subject;
private CallbackHandler _callbackHandler;
// username and password
private String _username;
private char[] _password;
/**
* Initialize this LoginModule.
*/
public void initialize(Subject subject, CallbackHandler callbackHandler,
Map sharedState, Map options) {
_subject = subject;
_callbackHandler = callbackHandler;
}
/**
* Method to authenticate a Subject (phase 1).
*/
public boolean login() throws LoginException {
Callback[] callbacks = new Callback[2];
// prompt for a username and password
if (_callbackHandler == null)
throw new LoginException("Error: no CallbackHandler available " +
"to garner authentication information from the user");
callbacks[0] = new NameCallback("User name: ", "guest");
callbacks[1] = new PasswordCallback("Password: ", false);
try {
_callbackHandler.handle(callbacks);
_username = ((NameCallback)callbacks[0]).getName();
char[] tmpPassword = ((PasswordCallback)callbacks[1]).getPassword();
if (tmpPassword != null) {
_password = new char[tmpPassword.length];
System.arraycopy(tmpPassword, 0, _password, 0, tmpPassword.length);
((PasswordCallback)callbacks[1]).clearPassword();
}
} catch (java.io.IOException ioe) {
throw new LoginException(ioe.toString());
} catch (UnsupportedCallbackException uce) {
throw new LoginException("Error: " + uce.getCallback().toString() +
" not available to garner authentication information " +
"from the user");
}
return true;
}
/**
* Method to commit the authentication process (phase 2).
*/
public boolean commit() throws LoginException {
SecurityAssociation.setPrincipal(new SimplePrincipal(_username));
SecurityAssociation.setCredential(_password);
return true;
}
/**
* Method to abort the authentication process (phase 2).
*/
public boolean abort() throws LoginException {
_username = null;
if (_password != null) {
for (int i = 0; i < _password.length; i++)
_password[i] = ' ';
_password = null;
}
return true;
}
public boolean logout() throws LoginException {
return true;
}
}
1.1 jboss/src/main/org/jboss/security/JaasSecurityManager.java
Index: JaasSecurityManager.java
===================================================================
/*
* jBoss, the OpenSource EJB server
*
* Distributable under GPL license.
* See terms of license at gnu.org.
*/
package org.jboss.security;
import java.io.File;
import java.net.URL;
import java.rmi.server.UnicastRemoteObject;
import java.rmi.RemoteException;
import java.rmi.ServerException;
import java.util.Set;
import java.util.HashMap;
import java.util.Arrays;
import java.util.Iterator;
import java.security.Principal;
import javax.security.auth.Subject;
import javax.security.auth.login.LoginContext;
import javax.security.auth.callback.CallbackHandler;
import javax.security.auth.callback.Callback;
import javax.security.auth.callback.NameCallback;
import javax.security.auth.callback.PasswordCallback;
import javax.security.auth.callback.UnsupportedCallbackException;
import javax.naming.InitialContext;
import javax.naming.Context;
import javax.naming.Reference;
import javax.naming.Name;
import javax.naming.spi.ObjectFactory;
import javax.management.MBeanServer;
import javax.management.ObjectName;
import javax.transaction.TransactionManager;
import org.jboss.logging.Log;
import org.jboss.util.ServiceMBeanSupport;
import org.jboss.system.EJBSecurityManager;
import org.jboss.system.RealmMapping;
/**
* The EJBSecurityManager is responsible for validating credentials
* associated with principals. Right now it is a "demo" that just
* ensures name == credential
*
* @see EJBSecurityManager
* @author <a href="[EMAIL PROTECTED]">Oleg Nitz</a>
*/
public class JaasSecurityManager implements EJBSecurityManager, RealmMapping {
/**
* Security manager name.
*/
private final String _smName;
/**
* Maps an original principal to authenticated client credential, aka password.
* Should be a time or size limited cache for better scalability.
* This is a master cache, when a principal is removed from this cache,
* the related entries from all other caches should be removed too.
*/
private final HashMap _passwords = new HashMap();
/**
* Maps original principal to principal for the bean.
*/
private final HashMap _principals = new HashMap();
/**
* Maps original principal to Set of roles for the bean.
*/
private final HashMap _roles = new HashMap();
/**
* @param smName The name of the security manager
*/
public JaasSecurityManager(String smName) {
_smName = smName;
}
public boolean isValid(Principal principal, Object credential) {
char[] authenticated;
authenticated = (char[]) _passwords.get(principal);
if (authenticated == null) {
return authenticate(_smName, principal, credential);
} else {
return (credential instanceof char[]) &&
Arrays.equals(authenticated, (char[]) credential);
}
}
public Principal getPrincipal(Principal principal) {
Principal result;
result = (Principal) _principals.get(principal);
if (result == null) {
if (authenticate(_smName, principal, null)) {
result = (Principal) _principals.get(principal);
}
}
return result;
}
public boolean doesUserHaveRole(Principal principal, Set roleNames)
{
Set roles;
Iterator it;
if (roleNames == null)
return true;
roles = (Set) _roles.get(principal);
if (roles == null) {
if (!authenticate(_smName, principal, null)) {
return false;
}
}
it = roleNames.iterator();
while (it.hasNext()) {
if (roles.contains(it.next())) {
return true;
}
}
return false;
}
/**
* @param bean The bean name
* @param userName The user name
* @param password The password
* @return false on failure, true on success.
*/
private boolean authenticate(String beanName, Principal principal, Object
credential) {
LoginContext lc;
Subject subj;
final String userName = principal.getName();
final char[] password = (char[]) credential;
Iterator it;
Principal beanPrincipal;
try {
lc = new LoginContext(beanName, new CallbackHandler() {
public void handle(Callback[] callbacks) throws
UnsupportedCallbackException {
for (int i = 0; i < callbacks.length; i++) {
if (callbacks[i] instanceof NameCallback) {
((NameCallback) callbacks[i]).setName(userName);
} else if (callbacks[i] instanceof PasswordCallback) {
((PasswordCallback) callbacks[i]).setPassword(password);
} else {
throw new UnsupportedCallbackException(callbacks[i],
"Unrecognized Callback");
}
}
}
});
lc.login();
_passwords.put(principal, password);
subj = lc.getSubject();
beanPrincipal = principal;
it = subj.getPrincipals().iterator();
if (it.hasNext()) {
beanPrincipal = (Principal) it.next();
}
_principals.put(principal, beanPrincipal);
_roles.put(principal, subj.getPublicCredentials());
return true;
} catch (Exception ex) {
return false;
}
}
}
1.1
jboss/src/main/org/jboss/security/JaasSecurityManagerService.java
Index: JaasSecurityManagerService.java
===================================================================
/*
* jBoss, the OpenSource EJB server
*
* Distributable under GPL license.
* See terms of license at gnu.org.
*/
package org.jboss.security;
import java.io.File;
import java.net.URL;
import java.rmi.server.UnicastRemoteObject;
import java.rmi.RemoteException;
import java.rmi.ServerException;
import java.util.Hashtable;
import java.util.ArrayList;
import java.util.Iterator;
import javax.naming.InitialContext;
import javax.naming.Context;
import javax.naming.Reference;
import javax.naming.Name;
import javax.naming.spi.ObjectFactory;
import javax.naming.CommunicationException;
import javax.management.MBeanServer;
import javax.management.ObjectName;
import javax.security.auth.login.Configuration;
import org.jboss.logging.Log;
import org.jboss.util.ServiceMBeanSupport;
import org.jboss.system.EJBSecurityManager;
/**
* This is a JMX service which manages the EJBSecurityManager.
* The service creates it and binds a Reference to it into JNDI.
* The EJBSecurityManager is responsible for validating credentials
* associated with principals.
*
* @see EJBSecurityManager
* @author <a href="[EMAIL PROTECTED]">Oleg Nitz</a>
*/
public class JaasSecurityManagerService
extends ServiceMBeanSupport
implements JaasSecurityManagerServiceMBean, ObjectFactory {
private static String JNDI_NAME = "jaas";
private static String JNDI_SM_CONTEXT_NAME = "jaas.sm";
MBeanServer server;
// smJndiNames and smContext must be static: they are used by
// ObjectFactory instances
private static ArrayList smJndiNames = new ArrayList();
private static Context smContext;
public String getName() {
return "JAAS Security Manager";
}
protected ObjectName getObjectName(MBeanServer server, ObjectName name)
throws javax.management.MalformedObjectNameException {
this.server = server;
return new ObjectName(OBJECT_NAME);
}
protected void initService() throws Exception {
InitialContext ic = new InitialContext();
// Bind reference to SM in JNDI
Reference ref = new Reference(JaasSecurityManager.class.getName(),
getClass().getName(), null);
ic.bind(JNDI_NAME, ref);
if (smContext == null) {
smContext = ic.createSubcontext(JNDI_SM_CONTEXT_NAME);
}
}
protected void startService()
throws Exception {
}
protected void stopService() {
InitialContext ic;
try {
ic = new InitialContext();
// Remove all SMs from JNDI
if (smContext != null) {
for (Iterator it = smJndiNames.iterator(); it.hasNext(); ) {
smContext.unbind((String) it.next());
it.remove();
}
ic.destroySubcontext(JNDI_SM_CONTEXT_NAME);
smContext = null;
}
ic.unbind(JNDI_NAME);
} catch (CommunicationException e) {
// Do nothing, the naming services is already stopped
} catch (Exception e) {
log.exception(e);
}
}
// ObjectFactory implementation ----------------------------------
public Object getObjectInstance(Object obj,
Name name,
Context nameCtx,
Hashtable environment)
throws Exception {
String smName = name.get(name.size() - 1);
if (!smJndiNames.contains(smName)) {
smContext.bind(smName, new JaasSecurityManager(smName));
smJndiNames.add(smName);
}
return smContext;
}
}
1.1
jboss/src/main/org/jboss/security/JaasSecurityManagerServiceMBean.java
Index: JaasSecurityManagerServiceMBean.java
===================================================================
/*
* jBoss, the OpenSource EJB server
*
* Distributable under GPL license.
* See terms of license at gnu.org.
*/
package org.jboss.security;
public interface JaasSecurityManagerServiceMBean
extends org.jboss.util.ServiceMBean
{
// Constants -----------------------------------------------------
public static final String OBJECT_NAME = ":service=JaasSecurityManager";
// Public --------------------------------------------------------
}
1.1 jboss/src/main/org/jboss/security/SimpleServerLoginModule.java
Index: SimpleServerLoginModule.java
===================================================================
/*
* jBoss, the OpenSource EJB server
*
* Distributable under GPL license.
* See terms of license at gnu.org.
*/
package org.jboss.security;
import java.util.Map;
import java.util.Set;
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.UnsupportedCallbackException;
import javax.security.auth.login.LoginException;
import javax.security.auth.login.FailedLoginException;
import javax.security.auth.spi.LoginModule;
import org.jboss.system.SecurityAssociation;
import org.jboss.system.SimplePrincipal;
/**
* This server login module implements the following simple algorithm:
* if password is null, authenticate the user and assign the "guest" role
* else if password is equal to the user name, assign both "user" and "guest" roles
* else don't authenticate.
*/
public class SimpleServerLoginModule implements LoginModule {
private Subject _subject;
private CallbackHandler _callbackHandler;
// username and password
private String _username;
private char[] _password;
/**
* Initialize this LoginModule.
*/
public void initialize(Subject subject, CallbackHandler callbackHandler,
Map sharedState, Map options) {
_subject = subject;
_callbackHandler = callbackHandler;
}
/**
* Method to authenticate a Subject (phase 1).
*/
public boolean login() throws LoginException {
Callback[] callbacks = new Callback[2];
// prompt for a username and password
if (_callbackHandler == null)
throw new LoginException("Error: no CallbackHandler available " +
"to garner authentication information from the user");
callbacks[0] = new NameCallback("User name: ", "guest");
callbacks[1] = new PasswordCallback("Password: ", false);
try {
_callbackHandler.handle(callbacks);
_username = ((NameCallback)callbacks[0]).getName();
char[] tmpPassword = ((PasswordCallback)callbacks[1]).getPassword();
if (tmpPassword != null) {
_password = new char[tmpPassword.length];
System.arraycopy(tmpPassword, 0, _password, 0, tmpPassword.length);
((PasswordCallback)callbacks[1]).clearPassword();
}
} catch (java.io.IOException ioe) {
throw new LoginException(ioe.toString());
} catch (UnsupportedCallbackException uce) {
throw new LoginException("Error: " + uce.getCallback().toString() +
" not available to garner authentication information " +
"from the user");
}
if (_password != null && !(new String(_password)).equals(_username)) {
throw new FailedLoginException("Password Incorrect");
}
return true;
}
/**
* Method to commit the authentication process (phase 2).
*/
public boolean commit() throws LoginException {
Set roles = _subject.getPublicCredentials();
roles.add("guest");
if (_password != null) {
roles.add("user");
}
return true;
}
/**
* Method to abort the authentication process (phase 2).
*/
public boolean abort() throws LoginException {
_username = null;
if (_password != null) {
for (int i = 0; i < _password.length; i++)
_password[i] = ' ';
_password = null;
}
return true;
}
public boolean logout() throws LoginException {
return true;
}
}