diff --git a/activemq-jaas/src/main/java/org/apache/activemq/jaas/GuestLoginModule.java b/activemq-jaas/src/main/java/org/apache/activemq/jaas/GuestLoginModule.java new file mode 100644 index 0000000000..ed8edba1ef --- /dev/null +++ b/activemq-jaas/src/main/java/org/apache/activemq/jaas/GuestLoginModule.java @@ -0,0 +1,104 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.activemq.jaas; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; + +import javax.security.auth.Subject; +import javax.security.auth.callback.CallbackHandler; +import javax.security.auth.login.LoginException; +import javax.security.auth.spi.LoginModule; +import java.security.Principal; +import java.util.HashSet; +import java.util.Map; +import java.util.Set; + +/** + * Always login the user with a default 'guest' identity. + * + * Useful for unauthenticated communication channels being used in the + * same broker as authenticated ones. + * + */ +public class GuestLoginModule implements LoginModule { + + private static final String GUEST_USER = "org.apache.activemq.jaas.guest.user"; + private static final String GUEST_GROUP = "org.apache.activemq.jaas.guest.group"; + + private static final Log LOG = LogFactory.getLog(GuestLoginModule.class); + + + private String userName = "guest"; + private String groupName = "guests"; + private Subject subject; + private boolean debug; + private Set principals = new HashSet(); + + + public void initialize(Subject subject, CallbackHandler callbackHandler, Map sharedState, Map options) { + this.subject = subject; + + debug = "true".equalsIgnoreCase((String)options.get("debug")); + if (options.get(GUEST_USER) != null) { + userName = (String)options.get(GUEST_USER); + } + if (options.get(GUEST_GROUP) != null) { + groupName = (String)options.get(GUEST_GROUP); + } + principals.add(new UserPrincipal(userName)); + principals.add(new GroupPrincipal(groupName)); + + if (debug) { + LOG.debug("Initialized debug=" + debug + " guestUser=" + userName + " guestGroup=" + groupName); + } + + } + + public boolean login() throws LoginException { + + if (debug) { + LOG.debug("login " + userName); + }return true; + } + + public boolean commit() throws LoginException { + subject.getPrincipals().addAll(principals); + + if (debug) { + LOG.debug("commit"); + } + return true; + } + + public boolean abort() throws LoginException { + + if (debug) { + LOG.debug("abort"); + } + return true; } + + public boolean logout() throws LoginException { + subject.getPrincipals().removeAll(principals); + + if (debug) { + LOG.debug("logout"); + } + return true; + } +} \ No newline at end of file diff --git a/activemq-jaas/src/test/java/org/apache/activemq/jaas/GuestLoginModuleTest.java b/activemq-jaas/src/test/java/org/apache/activemq/jaas/GuestLoginModuleTest.java new file mode 100644 index 0000000000..3b057827c3 --- /dev/null +++ b/activemq-jaas/src/test/java/org/apache/activemq/jaas/GuestLoginModuleTest.java @@ -0,0 +1,92 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.activemq.jaas; + +import java.io.IOException; +import java.net.URL; +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.LoginContext; +import javax.security.auth.login.LoginException; + +import junit.framework.TestCase; + + +/** + * @version $Rev: $ $Date: $ + */ +public class GuestLoginModuleTest extends TestCase { + + static { + String path = System.getProperty("java.security.auth.login.config"); + if (path == null) { + URL resource = GuestLoginModuleTest.class.getClassLoader().getResource("login.config"); + if (resource != null) { + path = resource.getFile(); + System.setProperty("java.security.auth.login.config", path); + } + } + } + + public void testLogin() throws LoginException { + LoginContext context = new LoginContext("GuestLogin", new CallbackHandler() { + public void handle(Callback[] callbacks) throws IOException, UnsupportedCallbackException { + assertEquals("Should have no Callbacks", 0, callbacks.length); + } + }); + context.login(); + + Subject subject = context.getSubject(); + + assertEquals("Should have two principals", 2, subject.getPrincipals().size()); + assertEquals("Should have one user principal", 1, subject.getPrincipals(UserPrincipal.class).size()); + assertTrue("User principal is 'foo'",subject.getPrincipals(UserPrincipal.class).contains(new UserPrincipal("foo"))); + + assertEquals("Should have one group principal", 1, subject.getPrincipals(GroupPrincipal.class).size()); + assertTrue("Group principal is 'bar'", subject.getPrincipals(GroupPrincipal.class).contains(new GroupPrincipal("bar"))); + + context.logout(); + + assertEquals("Should have zero principals", 0, subject.getPrincipals().size()); + } + + public void testLoginWithDefaults() throws LoginException { + LoginContext context = new LoginContext("GuestLoginWithDefaults", new CallbackHandler() { + public void handle(Callback[] callbacks) throws IOException, UnsupportedCallbackException { + assertEquals("Should have no Callbacks", 0, callbacks.length); + } + }); + context.login(); + + Subject subject = context.getSubject(); + + assertEquals("Should have two principals", 2, subject.getPrincipals().size()); + assertEquals("Should have one user principal", 1, subject.getPrincipals(UserPrincipal.class).size()); + assertTrue("User principal is 'guest'",subject.getPrincipals(UserPrincipal.class).contains(new UserPrincipal("guest"))); + + assertEquals("Should have one group principal", 1, subject.getPrincipals(GroupPrincipal.class).size()); + assertTrue("Group principal is 'guests'", subject.getPrincipals(GroupPrincipal.class).contains(new GroupPrincipal("guests"))); + + context.logout(); + + assertEquals("Should have zero principals", 0, subject.getPrincipals().size()); + } +} diff --git a/activemq-jaas/src/test/resources/login.config b/activemq-jaas/src/test/resources/login.config index 2843ba2a74..7dd4f00b57 100644 --- a/activemq-jaas/src/test/resources/login.config +++ b/activemq-jaas/src/test/resources/login.config @@ -40,3 +40,15 @@ LDAPLogin { ; }; +GuestLogin { + org.apache.activemq.jaas.GuestLoginModule required + debug=true + org.apache.activemq.jaas.guest.user="foo" + org.apache.activemq.jaas.guest.group="bar"; + +}; + +GuestLoginWithDefaults { + org.apache.activemq.jaas.GuestLoginModule required + debug=true; +};