You are viewing a plain text version of this content. The canonical link for it is here.
Posted to scm@geronimo.apache.org by as...@apache.org on 2010/06/28 10:49:00 UTC
svn commit: r958505 -
/geronimo/server/branches/2.1/framework/modules/geronimo-security/src/main/java/org/apache/geronimo/security/realm/providers/
Author: ashishjain
Date: Mon Jun 28 08:49:00 2010
New Revision: 958505
URL: http://svn.apache.org/viewvc?rev=958505&view=rev
Log:
GERONIMO-5197 Add generic header authentication modules for properties, ldap and sql.
Added:
geronimo/server/branches/2.1/framework/modules/geronimo-security/src/main/java/org/apache/geronimo/security/realm/providers/GenericHttpHeaderLdapLoginModule.java (with props)
geronimo/server/branches/2.1/framework/modules/geronimo-security/src/main/java/org/apache/geronimo/security/realm/providers/GenericHttpHeaderLoginmodule.java (with props)
geronimo/server/branches/2.1/framework/modules/geronimo-security/src/main/java/org/apache/geronimo/security/realm/providers/GenericHttpHeaderPropertiesFileLoginModule.java (with props)
geronimo/server/branches/2.1/framework/modules/geronimo-security/src/main/java/org/apache/geronimo/security/realm/providers/GenericHttpHeaderSqlLoginmodule.java (with props)
Added: geronimo/server/branches/2.1/framework/modules/geronimo-security/src/main/java/org/apache/geronimo/security/realm/providers/GenericHttpHeaderLdapLoginModule.java
URL: http://svn.apache.org/viewvc/geronimo/server/branches/2.1/framework/modules/geronimo-security/src/main/java/org/apache/geronimo/security/realm/providers/GenericHttpHeaderLdapLoginModule.java?rev=958505&view=auto
==============================================================================
--- geronimo/server/branches/2.1/framework/modules/geronimo-security/src/main/java/org/apache/geronimo/security/realm/providers/GenericHttpHeaderLdapLoginModule.java (added)
+++ geronimo/server/branches/2.1/framework/modules/geronimo-security/src/main/java/org/apache/geronimo/security/realm/providers/GenericHttpHeaderLdapLoginModule.java Mon Jun 28 08:49:00 2010
@@ -0,0 +1,440 @@
+package org.apache.geronimo.security.realm.providers;
+
+import java.io.IOException;
+import java.security.Principal;
+import java.text.MessageFormat;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.Hashtable;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+import javax.naming.AuthenticationException;
+import javax.naming.CommunicationException;
+import javax.naming.Context;
+import javax.naming.Name;
+import javax.naming.NameParser;
+import javax.naming.NamingEnumeration;
+import javax.naming.NamingException;
+import javax.naming.directory.Attribute;
+import javax.naming.directory.Attributes;
+import javax.naming.directory.DirContext;
+import javax.naming.directory.InitialDirContext;
+import javax.naming.directory.SearchControls;
+import javax.naming.directory.SearchResult;
+import javax.security.auth.Subject;
+import javax.security.auth.callback.Callback;
+import javax.security.auth.callback.CallbackHandler;
+import javax.security.auth.callback.UnsupportedCallbackException;
+import javax.security.auth.login.FailedLoginException;
+import javax.security.auth.login.LoginException;
+import javax.security.auth.spi.LoginModule;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.apache.geronimo.security.jaas.JaasLoginModuleUse;
+import org.apache.geronimo.security.jaas.WrappingLoginModule;
+
+public class GenericHttpHeaderLdapLoginModule extends GenericHttpHeaderLoginmodule implements LoginModule {
+
+ private static Log log = LogFactory.getLog(GenericHttpHeaderLdapLoginModule.class);
+
+ private final static String HEADER_NAMES="headerNames";
+ private final static String AUTHENTICATION_AUTHORITY="authenticationAuthority";
+ private static final String INITIAL_CONTEXT_FACTORY = "initialContextFactory";
+ private static final String CONNECTION_URL = "connectionURL";
+ private static final String CONNECTION_USERNAME = "connectionUsername";
+ private static final String CONNECTION_PASSWORD = "connectionPassword";
+ private static final String CONNECTION_PROTOCOL = "connectionProtocol";
+ private static final String AUTHENTICATION = "authentication";
+ private static final String USER_BASE = "userBase";
+ private static final String USER_SEARCH_MATCHING = "userSearchMatching";
+ private static final String USER_SEARCH_SUBTREE = "userSearchSubtree";
+ private static final String ROLE_BASE = "roleBase";
+ private static final String ROLE_NAME = "roleName";
+ private static final String ROLE_SEARCH_MATCHING = "roleSearchMatching";
+ private static final String ROLE_SEARCH_SUBTREE = "roleSearchSubtree";
+ private static final String USER_ROLE_NAME = "userRoleName";
+ public final static List<String> supportedOptions = Collections.unmodifiableList(Arrays.asList(INITIAL_CONTEXT_FACTORY, CONNECTION_URL,
+ CONNECTION_USERNAME,CONNECTION_PASSWORD, HEADER_NAMES, AUTHENTICATION_AUTHORITY, CONNECTION_PROTOCOL, AUTHENTICATION, USER_BASE,
+ USER_SEARCH_MATCHING, USER_SEARCH_SUBTREE, ROLE_BASE, ROLE_NAME, ROLE_SEARCH_MATCHING, ROLE_SEARCH_SUBTREE,
+ USER_ROLE_NAME));
+
+ private String initialContextFactory;
+ private String connectionURL;
+ private String connectionProtocol;
+ private String connectionUsername;
+ private String connectionPassword;
+ private String authentication;
+ private String userBase;
+ private String roleBase;
+ private String roleName;
+ private String userRoleName;
+
+ protected DirContext context = null;
+
+ private MessageFormat userSearchMatchingFormat;
+ private MessageFormat roleSearchMatchingFormat;
+
+ private boolean userSearchSubtreeBool = false;
+ private boolean roleSearchSubtreeBool = false;
+
+ private boolean loginSucceeded;
+ private final Set<String> groups = new HashSet<String>();
+ private final Set<Principal> allPrincipals = new HashSet<Principal>();
+
+ public void initialize(Subject subject, CallbackHandler callbackHandler, Map sharedState, Map options) {
+ this.subject = subject;
+ this.callbackHandler = callbackHandler;
+ for(Object option: options.keySet()) {
+ if(!supportedOptions.contains(option) && !JaasLoginModuleUse.supportedOptions.contains(option)
+ && !WrappingLoginModule.supportedOptions.contains(option)) {
+ log.warn("Ignoring option: "+option+". Not supported.");
+ }
+ }
+ headerNames= (String)options.get(HEADER_NAMES);
+ authenticationAuthority=(String)options.get(AUTHENTICATION_AUTHORITY);
+ initialContextFactory = (String) options.get(INITIAL_CONTEXT_FACTORY);
+ connectionURL = (String) options.get(CONNECTION_URL);
+ connectionUsername = (String) options.get(CONNECTION_USERNAME);
+ connectionPassword = (String) options.get(CONNECTION_PASSWORD);
+ connectionProtocol = (String) options.get(CONNECTION_PROTOCOL);
+ authentication = (String) options.get(AUTHENTICATION);
+ userBase = (String) options.get(USER_BASE);
+ String userSearchMatching = (String) options.get(USER_SEARCH_MATCHING);
+ String userSearchSubtree = (String) options.get(USER_SEARCH_SUBTREE);
+ roleBase = (String) options.get(ROLE_BASE);
+ roleName = (String) options.get(ROLE_NAME);
+ String roleSearchMatching = (String) options.get(ROLE_SEARCH_MATCHING);
+ String roleSearchSubtree = (String) options.get(ROLE_SEARCH_SUBTREE);
+ userRoleName = (String) options.get(USER_ROLE_NAME);
+ userSearchMatchingFormat = new MessageFormat(userSearchMatching);
+ roleSearchMatchingFormat = new MessageFormat(roleSearchMatching);
+ userSearchSubtreeBool = Boolean.valueOf(userSearchSubtree);
+ roleSearchSubtreeBool = Boolean.valueOf(roleSearchSubtree);
+ }
+
+ /**
+ * This LoginModule is not to be ignored. So, this method should never return false.
+ * @return true if authentication succeeds, or throw a LoginException such as FailedLoginException
+ * if authentication fails
+ */
+ public boolean login() throws LoginException {
+ Map<String,String> headerMap=null;
+ loginSucceeded = false;
+ Callback[] callbacks = new Callback[1];
+ callbacks[0]= new RequestCallback();
+ try {
+ callbackHandler.handle(callbacks);
+ } catch (IOException ioe) {
+ throw (LoginException) new LoginException().initCause(ioe);
+ } catch (UnsupportedCallbackException uce) {
+ throw (LoginException) new LoginException().initCause(uce);
+ }
+ httpRequest = ((RequestCallback) callbacks[0]).getRequest();
+ String []headers=headerNames.split(",");
+ try{
+ headerMap=matchHeaders(httpRequest, headers);
+ }
+ catch(HeaderMismatchException e){
+ throw (LoginException) new LoginException("Header Mistmatch error").initCause(e);
+ }
+
+ if(headerMap.isEmpty()){
+ throw new FailedLoginException();
+ }
+
+ if(authenticationAuthority.equalsIgnoreCase("Siteminder")){
+ HeaderHandler headerHandler= new SiteminderHeaderHandler();
+ username=headerHandler.getUser(headerMap);
+ }
+ else
+ if(authenticationAuthority.equalsIgnoreCase("Datapower"))
+ {
+ /*To be Done*/
+ }
+ if (username == null || username.equals("")) {
+ username = null;
+ throw new FailedLoginException();
+ }
+
+ try {
+ boolean result = authenticate(username);
+ if (!result) {
+ throw new FailedLoginException();
+ }
+ } catch (LoginException e) {
+ // Clear out the private state
+ username = null;
+ groups.clear();
+ throw e;
+ } catch (Exception e) {
+ // Clear out the private state
+ username = null;
+ groups.clear();
+ throw (LoginException) new LoginException("LDAP Error").initCause(e);
+ }
+
+ loginSucceeded = true;
+ return loginSucceeded;
+ }
+
+ /*
+ * @exception LoginException if login succeeded but commit failed.
+ *
+ * @return true if login succeeded and commit succeeded, or false if login failed but commit succeeded.
+ */
+ public boolean commit() throws LoginException {
+ if(loginSucceeded) {
+ for(String group: groups) {
+ allPrincipals.add(new GeronimoGroupPrincipal(group));
+ }
+ subject.getPrincipals().addAll(allPrincipals);
+ }
+
+ // Clear out the private state
+ username = null;
+ groups.clear();
+
+ return loginSucceeded;
+ }
+
+ public boolean abort() throws LoginException {
+ if(loginSucceeded) {
+ // Clear out the private state
+ username = null;
+ groups.clear();
+ allPrincipals.clear();
+ }
+ return loginSucceeded;
+ }
+
+ public boolean logout() throws LoginException {
+ // Clear out the private state
+ loginSucceeded = false;
+ username = null;
+ groups.clear();
+ if(!subject.isReadOnly()) {
+ // Remove principals added by this LoginModule
+ subject.getPrincipals().removeAll(allPrincipals);
+ }
+ allPrincipals.clear();
+ return true;
+ }
+
+ protected void close(DirContext context) {
+ try {
+ context.close();
+ } catch (Exception e) {
+ log.error(e);
+ }
+ }
+
+ protected boolean authenticate(String username) throws Exception {
+ DirContext context = open();
+ try {
+
+ String filter = userSearchMatchingFormat.format(new String[]{username});
+ SearchControls constraints = new SearchControls();
+ if (userSearchSubtreeBool) {
+ constraints.setSearchScope(SearchControls.SUBTREE_SCOPE);
+ } else {
+ constraints.setSearchScope(SearchControls.ONELEVEL_SCOPE);
+ }
+
+ //setup attributes
+ String[] attribs;
+ if (userRoleName == null) {
+ attribs = new String[]{};
+ } else {
+ attribs = new String[]{userRoleName};
+ }
+ constraints.setReturningAttributes(attribs);
+
+
+ NamingEnumeration results = context.search(userBase, filter, constraints);
+
+ if (results == null || !results.hasMore()) {
+ log.error("No roles associated with user "+username);
+ loginSucceeded=false;
+ throw new FailedLoginException();
+ }
+
+ SearchResult result = (SearchResult) results.next();
+
+ if (results.hasMore()) {
+ //ignore for now
+ }
+ NameParser parser = context.getNameParser("");
+ Name contextName = parser.parse(context.getNameInNamespace());
+ Name baseName = parser.parse(userBase);
+ Name entryName = parser.parse(result.getName());
+ Name name = contextName.addAll(baseName);
+ name = name.addAll(entryName);
+ String dn = name.toString();
+
+ Attributes attrs = result.getAttributes();
+ if (attrs == null) {
+ return false;
+ }
+ ArrayList<String> roles = null;
+ if (userRoleName != null) {
+ roles = addAttributeValues(userRoleName, attrs, roles);
+ }
+ //check the credentials by binding to server
+ // bindUser(context, dn);
+ //if authenticated add more roles
+ roles = getRoles(context, dn, username, roles);
+ for (String role : roles) {
+ groups.add(role);
+ }
+ if(groups.isEmpty()){
+ log.error("No roles associated with user "+username);
+ loginSucceeded=false;
+ throw new FailedLoginException();
+ }
+ else
+ loginSucceeded=true;
+
+ } catch (CommunicationException e) {
+ close(context);
+ throw (LoginException) new FailedLoginException().initCause(e);
+ } catch (NamingException e) {
+ close(context);
+ throw (LoginException) new FailedLoginException().initCause(e);
+ }
+ return true;
+ }
+
+ protected ArrayList<String> getRoles(DirContext context, String dn, String username, ArrayList<String> list) throws NamingException {
+ if (list == null) {
+ list = new ArrayList<String>();
+ }
+ if (roleName == null || "".equals(roleName)) {
+ return list;
+ }
+ String filter = roleSearchMatchingFormat.format(new String[]{doRFC2254Encoding(dn), username});
+
+ SearchControls constraints = new SearchControls();
+ if (roleSearchSubtreeBool) {
+ constraints.setSearchScope(SearchControls.SUBTREE_SCOPE);
+ } else {
+ constraints.setSearchScope(SearchControls.ONELEVEL_SCOPE);
+ }
+ NamingEnumeration results =
+ context.search(roleBase, filter, constraints);
+ while (results.hasMore()) {
+ SearchResult result = (SearchResult) results.next();
+ Attributes attrs = result.getAttributes();
+ if (attrs == null) {
+ continue;
+ }
+ list = addAttributeValues(roleName, attrs, list);
+ }
+ return list;
+ }
+
+
+ protected String doRFC2254Encoding(String inputString) {
+ StringBuffer buf = new StringBuffer(inputString.length());
+ for (int i = 0; i < inputString.length(); i++) {
+ char c = inputString.charAt(i);
+ switch (c) {
+ case'\\':
+ buf.append("\\5c");
+ break;
+ case'*':
+ buf.append("\\2a");
+ break;
+ case'(':
+ buf.append("\\28");
+ break;
+ case')':
+ buf.append("\\29");
+ break;
+ case'\0':
+ buf.append("\\00");
+ break;
+ default:
+ buf.append(c);
+ break;
+ }
+ }
+ return buf.toString();
+ }
+
+ protected void bindUser(DirContext context, String dn) throws NamingException, FailedLoginException {
+
+ context.addToEnvironment(Context.SECURITY_PRINCIPAL, dn);
+ try {
+ context.getAttributes("", null);
+ } catch (AuthenticationException e) {
+ log.debug("Authentication failed for dn=" + dn);
+ throw new FailedLoginException();
+ } finally {
+
+ if (connectionUsername != null) {
+ context.addToEnvironment(Context.SECURITY_PRINCIPAL,
+ connectionUsername);
+ } else {
+ context.removeFromEnvironment(Context.SECURITY_PRINCIPAL);
+ }
+
+ if (connectionPassword != null) {
+ context.addToEnvironment(Context.SECURITY_CREDENTIALS,
+ connectionPassword);
+ } else {
+ context.removeFromEnvironment(Context.SECURITY_CREDENTIALS);
+ }
+ }
+ }
+
+ private ArrayList<String> addAttributeValues(String attrId, Attributes attrs, ArrayList<String> values)
+ throws NamingException {
+
+ if (attrId == null || attrs == null) {
+ return values;
+ }
+ if (values == null) {
+ values = new ArrayList<String>();
+ }
+ Attribute attr = attrs.get(attrId);
+ if (attr == null) {
+ return (values);
+ }
+ NamingEnumeration e = attr.getAll();
+ while (e.hasMore()) {
+ String value = (String) e.next();
+ values.add(value);
+ }
+ return values;
+ }
+
+ protected DirContext open() throws NamingException {
+ if (context != null) {
+ return context;
+ }
+ try {
+ Hashtable<String, String> env = new Hashtable<String, String>();
+ env.put(Context.INITIAL_CONTEXT_FACTORY, initialContextFactory);
+ if (connectionUsername != null || !"".equals(connectionUsername)) {
+ env.put(Context.SECURITY_PRINCIPAL, connectionUsername);
+ }
+ if (connectionPassword != null || !"".equals(connectionPassword)) {
+ env.put(Context.SECURITY_CREDENTIALS, connectionPassword);
+ }
+ env.put(Context.SECURITY_PROTOCOL, connectionProtocol == null ? "" : connectionProtocol);
+ env.put(Context.PROVIDER_URL, connectionURL == null ? "" : connectionURL);
+ env.put(Context.SECURITY_AUTHENTICATION, authentication == null ? "" : authentication);
+ context = new InitialDirContext(env);
+
+ } catch (NamingException e) {
+ log.error(e);
+ throw e;
+ }
+ return context;
+ }
+}
Propchange: geronimo/server/branches/2.1/framework/modules/geronimo-security/src/main/java/org/apache/geronimo/security/realm/providers/GenericHttpHeaderLdapLoginModule.java
------------------------------------------------------------------------------
svn:eol-style = native
Propchange: geronimo/server/branches/2.1/framework/modules/geronimo-security/src/main/java/org/apache/geronimo/security/realm/providers/GenericHttpHeaderLdapLoginModule.java
------------------------------------------------------------------------------
svn:keywords = Date Revision
Propchange: geronimo/server/branches/2.1/framework/modules/geronimo-security/src/main/java/org/apache/geronimo/security/realm/providers/GenericHttpHeaderLdapLoginModule.java
------------------------------------------------------------------------------
svn:mime-type = text/plain
Added: geronimo/server/branches/2.1/framework/modules/geronimo-security/src/main/java/org/apache/geronimo/security/realm/providers/GenericHttpHeaderLoginmodule.java
URL: http://svn.apache.org/viewvc/geronimo/server/branches/2.1/framework/modules/geronimo-security/src/main/java/org/apache/geronimo/security/realm/providers/GenericHttpHeaderLoginmodule.java?rev=958505&view=auto
==============================================================================
--- geronimo/server/branches/2.1/framework/modules/geronimo-security/src/main/java/org/apache/geronimo/security/realm/providers/GenericHttpHeaderLoginmodule.java (added)
+++ geronimo/server/branches/2.1/framework/modules/geronimo-security/src/main/java/org/apache/geronimo/security/realm/providers/GenericHttpHeaderLoginmodule.java Mon Jun 28 08:49:00 2010
@@ -0,0 +1,73 @@
+package org.apache.geronimo.security.realm.providers;
+
+import java.security.Principal;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Map;
+import java.util.Set;
+
+import javax.security.auth.Subject;
+import javax.security.auth.callback.CallbackHandler;
+import javax.servlet.http.HttpServletRequest;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.apache.geronimo.management.geronimo.JCAManagedConnectionFactory;
+/*
+ * Parent class for all the generic header login modules.
+ */
+public abstract class GenericHttpHeaderLoginmodule {
+
+ private static Log log = LogFactory.getLog(GenericHttpHeaderLoginmodule.class);
+
+ protected Subject subject;
+ protected String username;
+ protected String headerNames;
+ protected String authenticationAuthority;
+ protected JCAManagedConnectionFactory factory;
+ protected CallbackHandler callbackHandler;
+ protected boolean loginSucceeded;
+ protected HttpServletRequest httpRequest;
+ protected Set<Principal> allPrincipals = new HashSet<Principal>();
+ protected Set<String> groups = new HashSet<String>();
+
+ public GenericHttpHeaderLoginmodule(){
+
+ }
+
+ protected void commitHelper(){
+ for(String group:groups){
+ allPrincipals.add(new GeronimoGroupPrincipal(group));
+ }
+ subject.getPrincipals().addAll(allPrincipals);
+ subject.getPublicCredentials().add(username);
+ }
+
+ public void abortHelper(){
+ allPrincipals.clear();
+ groups.clear();
+ }
+
+ public void logoutHelper(){
+ groups.clear();
+ if(!subject.isReadOnly()) {
+ // Remove principals added by this LoginModule
+ subject.getPrincipals().removeAll(allPrincipals);
+ }
+ allPrincipals.clear();
+ }
+
+ public Map<String, String> matchHeaders(HttpServletRequest request, String[] headers) throws HeaderMismatchException{
+ Map<String,String> headerMap= new HashMap<String, String>();
+ for(String header:headers){
+ String headerValue=request.getHeader(header);
+ if(headerValue!=null){
+ headerMap.put(header, headerValue);
+ }
+ else
+ log.warn("An Unauthorized attempt has been made to access the protected resource from host "+request.getRemoteHost());
+ }
+ return headerMap;
+ }
+
+}
Propchange: geronimo/server/branches/2.1/framework/modules/geronimo-security/src/main/java/org/apache/geronimo/security/realm/providers/GenericHttpHeaderLoginmodule.java
------------------------------------------------------------------------------
svn:eol-style = native
Propchange: geronimo/server/branches/2.1/framework/modules/geronimo-security/src/main/java/org/apache/geronimo/security/realm/providers/GenericHttpHeaderLoginmodule.java
------------------------------------------------------------------------------
svn:keywords = Date Revision
Propchange: geronimo/server/branches/2.1/framework/modules/geronimo-security/src/main/java/org/apache/geronimo/security/realm/providers/GenericHttpHeaderLoginmodule.java
------------------------------------------------------------------------------
svn:mime-type = text/plain
Added: geronimo/server/branches/2.1/framework/modules/geronimo-security/src/main/java/org/apache/geronimo/security/realm/providers/GenericHttpHeaderPropertiesFileLoginModule.java
URL: http://svn.apache.org/viewvc/geronimo/server/branches/2.1/framework/modules/geronimo-security/src/main/java/org/apache/geronimo/security/realm/providers/GenericHttpHeaderPropertiesFileLoginModule.java?rev=958505&view=auto
==============================================================================
--- geronimo/server/branches/2.1/framework/modules/geronimo-security/src/main/java/org/apache/geronimo/security/realm/providers/GenericHttpHeaderPropertiesFileLoginModule.java (added)
+++ geronimo/server/branches/2.1/framework/modules/geronimo-security/src/main/java/org/apache/geronimo/security/realm/providers/GenericHttpHeaderPropertiesFileLoginModule.java Mon Jun 28 08:49:00 2010
@@ -0,0 +1,200 @@
+package org.apache.geronimo.security.realm.providers;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.net.URI;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.Enumeration;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Properties;
+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.UnsupportedCallbackException;
+import javax.security.auth.login.FailedLoginException;
+import javax.security.auth.login.LoginException;
+import javax.security.auth.spi.LoginModule;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.apache.geronimo.common.GeronimoSecurityException;
+import org.apache.geronimo.security.jaas.JaasLoginModuleUse;
+import org.apache.geronimo.security.jaas.WrappingLoginModule;
+import org.apache.geronimo.system.serverinfo.ServerInfo;
+
+public class GenericHttpHeaderPropertiesFileLoginModule extends GenericHttpHeaderLoginmodule implements LoginModule {
+ private final static String GROUPS_URI = "groupsURI";
+ private final static String HEADER_NAMES="headerNames";
+ private final static String AUTHENTICATION_AUTHORITY="authenticationAuthority";
+
+ public final static List<String> supportedOptions = Collections.unmodifiableList(Arrays.asList(GROUPS_URI, HEADER_NAMES, AUTHENTICATION_AUTHORITY));
+ private static Log log = LogFactory.getLog(PropertiesFileLoginModule.class);
+ final Map<String, Set<String>> roleUsersMap = new HashMap<String, Set<String>>();
+
+
+ public void initialize(Subject subject, CallbackHandler callbackHandler, Map sharedState, Map options) {
+ this.subject = subject;
+ this.callbackHandler = callbackHandler;
+ headerNames= (String)options.get(HEADER_NAMES);
+ authenticationAuthority=(String)options.get(AUTHENTICATION_AUTHORITY);
+
+ for(Object option: options.keySet()) {
+ if(!supportedOptions.contains(option) && !JaasLoginModuleUse.supportedOptions.contains(option)
+ && !WrappingLoginModule.supportedOptions.contains(option)) {
+ log.warn("Ignoring option: "+option+". Not supported.");
+ }
+ }
+ try {
+ ServerInfo serverInfo = (ServerInfo) options.get(JaasLoginModuleUse.SERVERINFO_LM_OPTION);
+ final String groups = (String) options.get(GROUPS_URI);
+
+ if (groups == null) {
+ throw new IllegalArgumentException(GROUPS_URI + " must be provided!");
+ }
+ URI groupsURI = new URI(groups);
+ loadProperties(serverInfo, groupsURI);
+ } catch (Exception e) {
+ log.error("Initialization failed", e);
+ throw new IllegalArgumentException("Unable to configure properties file login module: " + e.getMessage(),
+ e);
+ }
+ }
+
+ public void loadProperties(ServerInfo serverInfo, URI groupURI) throws GeronimoSecurityException {
+ try {
+ URI groupFile = serverInfo.resolveServer(groupURI);
+ Properties temp = new Properties();
+ InputStream stream = groupFile.toURL().openStream();
+ temp.load(stream);
+ stream.close();
+
+ Enumeration e = temp.keys();
+ while (e.hasMoreElements()) {
+ String groupName = (String) e.nextElement();
+ String[] userList = ((String) temp.get(groupName)).split(",");
+
+ Set<String> userset = roleUsersMap.get(groupName);
+ if (userset == null) {
+ userset = new HashSet<String>();
+ roleUsersMap.put(groupName, userset);
+ }
+ for (String user : userList) {
+ userset.add(user);
+ }
+ }
+
+ } catch (Exception e) {
+ log.error("Generic HTTP Header Properties File Login Module - data load failed", e);
+ throw new GeronimoSecurityException(e);
+ }
+ }
+
+ public boolean login() throws LoginException {
+ Map<String,String> headerMap=null;
+ loginSucceeded = false;
+ Callback[] callbacks = new Callback[1];
+ callbacks[0]= new RequestCallback();
+ try {
+ callbackHandler.handle(callbacks);
+ } catch (IOException ioe) {
+ throw (LoginException) new LoginException().initCause(ioe);
+ } catch (UnsupportedCallbackException uce) {
+ throw (LoginException) new LoginException().initCause(uce);
+ }
+ httpRequest = ((RequestCallback) callbacks[0]).getRequest();
+ String []headers=headerNames.split(",");
+ try{
+ headerMap=matchHeaders(httpRequest, headers);
+ }
+ catch(HeaderMismatchException e){
+ throw (LoginException) new LoginException("Header Mistmatch error").initCause(e);
+ }
+
+ if(headerMap.isEmpty()){
+ throw new FailedLoginException();
+ }
+
+ if(authenticationAuthority.equalsIgnoreCase("Siteminder")){
+ HeaderHandler headerHandler= new SiteminderHeaderHandler();
+ username=headerHandler.getUser(headerMap);
+ }
+ else
+ if(authenticationAuthority.equalsIgnoreCase("Datapower"))
+ {
+ /*To be Done*/
+ }
+ if (username == null || username.equals("")) {
+ username = null;
+ throw new FailedLoginException();
+ }
+
+ if(username!= null) {
+ for (Map.Entry<String, Set<String>> entry : roleUsersMap.entrySet()) {
+ String groupName = entry.getKey();
+ Set<String> users = entry.getValue();
+ for (String user : users) {
+ if (username.equals(user)) {
+ groups.add(groupName);
+ break;
+ }
+ }
+ }
+ }
+
+ if(groups.isEmpty()){
+ log.error("No roles associated with user "+username);
+ loginSucceeded=false;
+ throw new FailedLoginException();
+ }
+ else
+ loginSucceeded=true;
+ return loginSucceeded;
+ }
+
+ /*
+ * @exception LoginException if login succeeded but commit failed.
+ *
+ * @return true if login succeeded and commit succeeded, or false if login failed but commit succeeded.
+ */
+ public boolean commit() throws LoginException {
+ if(loginSucceeded) {
+ if(username != null) {
+ super.commitHelper();
+ }
+ }
+
+ // Clear out the private state
+ username = null;
+ roleUsersMap.clear();
+ groups.clear();
+
+ return loginSucceeded;
+ }
+
+ public boolean abort() throws LoginException {
+ if(loginSucceeded) {
+ // Clear out the private state
+ username = null;
+ allPrincipals.clear();
+ }
+ return loginSucceeded;
+ }
+
+ public boolean logout() throws LoginException {
+ // Clear out the private state
+ loginSucceeded = false;
+ username = null;
+ if(!subject.isReadOnly()) {
+ // Remove principals added by this LoginModule
+ subject.getPrincipals().removeAll(allPrincipals);
+ }
+ allPrincipals.clear();
+ return true;
+ }
+}
Propchange: geronimo/server/branches/2.1/framework/modules/geronimo-security/src/main/java/org/apache/geronimo/security/realm/providers/GenericHttpHeaderPropertiesFileLoginModule.java
------------------------------------------------------------------------------
svn:eol-style = native
Propchange: geronimo/server/branches/2.1/framework/modules/geronimo-security/src/main/java/org/apache/geronimo/security/realm/providers/GenericHttpHeaderPropertiesFileLoginModule.java
------------------------------------------------------------------------------
svn:keywords = Date Revision
Propchange: geronimo/server/branches/2.1/framework/modules/geronimo-security/src/main/java/org/apache/geronimo/security/realm/providers/GenericHttpHeaderPropertiesFileLoginModule.java
------------------------------------------------------------------------------
svn:mime-type = text/plain
Added: geronimo/server/branches/2.1/framework/modules/geronimo-security/src/main/java/org/apache/geronimo/security/realm/providers/GenericHttpHeaderSqlLoginmodule.java
URL: http://svn.apache.org/viewvc/geronimo/server/branches/2.1/framework/modules/geronimo-security/src/main/java/org/apache/geronimo/security/realm/providers/GenericHttpHeaderSqlLoginmodule.java?rev=958505&view=auto
==============================================================================
--- geronimo/server/branches/2.1/framework/modules/geronimo-security/src/main/java/org/apache/geronimo/security/realm/providers/GenericHttpHeaderSqlLoginmodule.java (added)
+++ geronimo/server/branches/2.1/framework/modules/geronimo-security/src/main/java/org/apache/geronimo/security/realm/providers/GenericHttpHeaderSqlLoginmodule.java Mon Jun 28 08:49:00 2010
@@ -0,0 +1,234 @@
+package org.apache.geronimo.security.realm.providers;
+
+import java.io.IOException;
+import java.sql.Connection;
+import java.sql.PreparedStatement;
+import java.sql.ResultSet;
+import java.sql.SQLException;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.List;
+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.UnsupportedCallbackException;
+import javax.security.auth.login.FailedLoginException;
+import javax.security.auth.login.LoginException;
+import javax.security.auth.spi.LoginModule;
+import javax.sql.DataSource;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.apache.geronimo.gbean.AbstractName;
+import org.apache.geronimo.gbean.AbstractNameQuery;
+import org.apache.geronimo.j2ee.j2eeobjectnames.NameFactory;
+import org.apache.geronimo.kernel.GBeanNotFoundException;
+import org.apache.geronimo.kernel.Kernel;
+import org.apache.geronimo.kernel.KernelRegistry;
+import org.apache.geronimo.management.geronimo.JCAManagedConnectionFactory;
+import org.apache.geronimo.security.jaas.JaasLoginModuleUse;
+import org.apache.geronimo.security.jaas.WrappingLoginModule;
+
+
+public class GenericHttpHeaderSqlLoginmodule extends GenericHttpHeaderLoginmodule implements LoginModule {
+ private static Log log = LogFactory.getLog(GenericHttpHeaderSqlLoginmodule.class);
+
+ private final static String GROUP_SELECT = "groupSelect";
+ private final static String USER = "jdbcUser";
+ private final static String DATABASE_POOL_NAME = "dataSourceName";
+ private final static String DATABASE_POOL_APP_NAME = "dataSourceApplication";
+ private final static String HEADER_NAMES="headerNames";
+ private final static String AUTHENTICATION_AUTHORITY="authenticationAuthority";
+ private final static List<String> supportedOptions = Collections.unmodifiableList(Arrays.asList(GROUP_SELECT, USER,
+ DATABASE_POOL_NAME, DATABASE_POOL_APP_NAME,HEADER_NAMES,AUTHENTICATION_AUTHORITY));
+ private String groupSelect;
+
+ public boolean abort() throws LoginException {
+ if(loginSucceeded) {
+ // Clear out the private state
+ username = null;
+ groups.clear();
+ allPrincipals.clear();
+ }
+ return loginSucceeded;
+ }
+
+ public boolean commit() throws LoginException {
+ if(loginSucceeded) {
+ if(username != null) {
+ super.commitHelper();
+ }
+ }
+
+ // Clear out the private state
+ username = null;
+ groups.clear();
+
+ return loginSucceeded;
+ }
+
+ public void initialize(Subject subject, CallbackHandler callbackHandler, Map<String, ?> sharedState,
+ Map<String, ?> options) {
+ this.subject = subject;
+ this.callbackHandler = callbackHandler;
+ for (Object option : options.keySet()) {
+ if (!supportedOptions.contains(option) && !JaasLoginModuleUse.supportedOptions.contains(option)
+ && !WrappingLoginModule.supportedOptions.contains(option)) {
+ log.warn("Ignoring option: " + option + ". Not supported.");
+ }
+ }
+ headerNames= (String)options.get(HEADER_NAMES);
+ authenticationAuthority=(String)options.get(AUTHENTICATION_AUTHORITY);
+ groupSelect = (String) options.get(GROUP_SELECT);
+ String dataSourceName = (String) options.get(DATABASE_POOL_NAME);
+ if (dataSourceName != null) {
+ dataSourceName = dataSourceName.trim();
+ String dataSourceAppName = (String) options.get(DATABASE_POOL_APP_NAME);
+ if (dataSourceAppName == null || dataSourceAppName.trim().equals("")) {
+ dataSourceAppName = "null";
+ } else {
+ dataSourceAppName = dataSourceAppName.trim();
+ }
+ String kernelName = (String) options.get(JaasLoginModuleUse.KERNEL_NAME_LM_OPTION);
+ Kernel kernel = KernelRegistry.getKernel(kernelName);
+ Set<AbstractName> set = kernel.listGBeans(new AbstractNameQuery(JCAManagedConnectionFactory.class.getName()));
+ JCAManagedConnectionFactory factory;
+ for (AbstractName name : set) {
+ if (name.getName().get(NameFactory.J2EE_APPLICATION).equals(dataSourceAppName)
+ && name.getName().get(NameFactory.J2EE_NAME).equals(dataSourceName)) {
+ try {
+ factory = (JCAManagedConnectionFactory) kernel.getGBean(name);
+ String type = factory.getConnectionFactoryInterface();
+ if (type.equals(DataSource.class.getName())) {
+ this.factory = factory;
+ break;
+ }
+ } catch (GBeanNotFoundException e) {
+ // ignore... GBean was unregistered
+ }
+ }
+ }
+ }
+ }
+
+ public boolean login() throws LoginException {
+ Map<String,String> headerMap=null;
+ loginSucceeded = false;
+ Connection conn=null;
+ ResultSet result=null;
+ PreparedStatement statement=null;
+ Callback[] callbacks = new Callback[1];
+ callbacks[0]= new RequestCallback();
+ try {
+ callbackHandler.handle(callbacks);
+ } catch (IOException ioe) {
+ throw (LoginException) new LoginException().initCause(ioe);
+ } catch (UnsupportedCallbackException uce) {
+ throw (LoginException) new LoginException().initCause(uce);
+ }
+ httpRequest = ((RequestCallback) callbacks[0]).getRequest();
+ String []headers=headerNames.split(",");
+ try{
+ headerMap=matchHeaders(httpRequest, headers);
+ }
+ catch(HeaderMismatchException e){
+ throw (LoginException) new LoginException("Header Mistmatch error").initCause(e);
+ }
+
+ if(headerMap.isEmpty()){
+ throw new FailedLoginException();
+ }
+
+ if(authenticationAuthority.equalsIgnoreCase("Siteminder")){
+ HeaderHandler headerHandler= new SiteminderHeaderHandler();
+ username=headerHandler.getUser(headerMap);
+ }
+ else
+ if(authenticationAuthority.equalsIgnoreCase("Datapower"))
+ {
+ /*To be Done*/
+ }
+ if (username == null || username.equals("")) {
+ username = null;
+ throw new FailedLoginException();
+ }
+
+ if (factory != null) {
+ DataSource ds;
+ try {
+ ds = (DataSource) factory.getConnectionFactory();
+ conn = ds.getConnection();
+
+ try {
+ statement = conn.prepareStatement(groupSelect);
+ int count = countParameters(groupSelect);
+ for (int i = 0; i < count; i++) {
+ statement.setObject(i + 1, username);
+ }
+ result = statement.executeQuery();
+ while (result.next()) {
+ String userName = result.getString(1);
+ String groupName = result.getString(2);
+ if(userName.equals(username))
+ groups.add(groupName);
+ }
+ if(groups.isEmpty()){
+ log.error("No roles associated with user "+username);
+ loginSucceeded=false;
+ throw new FailedLoginException();
+ }
+ else
+ loginSucceeded=true;
+ }
+ finally{
+ result.close();
+ statement.close();
+ conn.close();
+ }
+ }
+ catch (LoginException e) {
+ // Clear out the private state
+ username = null;
+ groups.clear();
+ throw e;
+ } catch (SQLException sqle) {
+ // Clear out the private state
+ username = null;
+ groups.clear();
+ throw (LoginException) new LoginException("SQL error").initCause(sqle);
+ } catch (Exception e) {
+ // Clear out the private state
+ username = null;
+ groups.clear();
+ throw (LoginException) new LoginException("Could not access datasource").initCause(e);
+ }
+ }
+
+ return loginSucceeded;
+ }
+
+ public boolean logout() throws LoginException {
+ loginSucceeded = false;
+ username = null;
+ groups.clear();
+ if(!subject.isReadOnly()) {
+ // Remove principals added by this LoginModule
+ subject.getPrincipals().removeAll(allPrincipals);
+ }
+ allPrincipals.clear();
+ return true;
+ }
+
+ private static int countParameters(String sql) {
+ int count = 0;
+ int pos = -1;
+ while ((pos = sql.indexOf('?', pos + 1)) != -1) {
+ ++count;
+ }
+ return count;
+ }
+
+}
Propchange: geronimo/server/branches/2.1/framework/modules/geronimo-security/src/main/java/org/apache/geronimo/security/realm/providers/GenericHttpHeaderSqlLoginmodule.java
------------------------------------------------------------------------------
svn:eol-style = native
Propchange: geronimo/server/branches/2.1/framework/modules/geronimo-security/src/main/java/org/apache/geronimo/security/realm/providers/GenericHttpHeaderSqlLoginmodule.java
------------------------------------------------------------------------------
svn:keywords = Date Revision
Propchange: geronimo/server/branches/2.1/framework/modules/geronimo-security/src/main/java/org/apache/geronimo/security/realm/providers/GenericHttpHeaderSqlLoginmodule.java
------------------------------------------------------------------------------
svn:mime-type = text/plain