001/**
002 * Licensed to the Apache Software Foundation (ASF) under one or more
003 * contributor license agreements.  See the NOTICE file distributed with
004 * this work for additional information regarding copyright ownership.
005 * The ASF licenses this file to You under the Apache License, Version 2.0
006 * (the "License"); you may not use this file except in compliance with
007 * the License.  You may obtain a copy of the License at
008 *
009 *      http://www.apache.org/licenses/LICENSE-2.0
010 *
011 * Unless required by applicable law or agreed to in writing, software
012 * distributed under the License is distributed on an "AS IS" BASIS,
013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014 * See the License for the specific language governing permissions and
015 * limitations under the License.
016 */
017
018package org.apache.activemq.jaas;
019
020import java.io.IOException;
021import java.security.Principal;
022import java.util.HashSet;
023import java.util.Map;
024import java.util.Set;
025import javax.security.auth.Subject;
026import javax.security.auth.callback.Callback;
027import javax.security.auth.callback.CallbackHandler;
028import javax.security.auth.callback.PasswordCallback;
029import javax.security.auth.callback.UnsupportedCallbackException;
030import javax.security.auth.login.LoginException;
031import javax.security.auth.spi.LoginModule;
032import org.slf4j.Logger;
033import org.slf4j.LoggerFactory;
034
035/**
036 * Always login the user with a default 'guest' identity.
037 *
038 * Useful for unauthenticated communication channels being used in the
039 * same broker as authenticated ones.
040 * 
041 */
042public class GuestLoginModule implements LoginModule {
043
044    private static final String GUEST_USER = "org.apache.activemq.jaas.guest.user";
045    private static final String GUEST_GROUP = "org.apache.activemq.jaas.guest.group";
046
047    private static final Logger LOG = LoggerFactory.getLogger(GuestLoginModule.class);
048    
049
050    private String userName = "guest";
051    private String groupName = "guests";
052    private Subject subject;
053    private boolean debug;
054    private boolean credentialsInvalidate;
055    private Set<Principal> principals = new HashSet<Principal>();
056    private CallbackHandler callbackHandler;
057    private boolean loginSucceeded;
058
059    @Override
060    public void initialize(Subject subject, CallbackHandler callbackHandler, Map sharedState, Map options) {
061        this.subject = subject;
062        this.callbackHandler = callbackHandler;
063        debug = "true".equalsIgnoreCase((String)options.get("debug"));
064        credentialsInvalidate = "true".equalsIgnoreCase((String)options.get("credentialsInvalidate"));
065        if (options.get(GUEST_USER) != null) {
066            userName = (String)options.get(GUEST_USER);
067        }
068        if (options.get(GUEST_GROUP) != null) {
069            groupName = (String)options.get(GUEST_GROUP);
070        }
071        principals.add(new UserPrincipal(userName));
072        principals.add(new GroupPrincipal(groupName));
073        
074        if (debug) {
075            LOG.debug("Initialized debug=" + debug + " guestUser=" + userName + " guestGroup=" + groupName);
076        }
077
078    }
079
080    @Override
081    public boolean login() throws LoginException {
082        loginSucceeded = true;
083        if (credentialsInvalidate) {
084            PasswordCallback passwordCallback = new PasswordCallback("Password: ", false);
085            try {
086                 callbackHandler.handle(new Callback[]{passwordCallback});
087                 if (passwordCallback.getPassword() != null) {
088                     if (debug) {
089                        LOG.debug("Guest login failing (credentialsInvalidate=true) on presence of a password");
090                     }
091                     loginSucceeded = false;
092                     passwordCallback.clearPassword();
093                 };
094             } catch (IOException ioe) {
095             } catch (UnsupportedCallbackException uce) {
096             }
097        }
098        if (debug) {
099            LOG.debug("Guest login " + loginSucceeded);
100        }
101        return loginSucceeded;
102    }
103
104    @Override
105    public boolean commit() throws LoginException {
106        if (loginSucceeded) {
107            subject.getPrincipals().addAll(principals);
108        }
109
110        if (debug) {
111            LOG.debug("commit");
112        }
113        return loginSucceeded;
114    }
115
116    @Override
117    public boolean abort() throws LoginException {
118
119        if (debug) {
120            LOG.debug("abort");
121        }
122        return true;
123    }
124
125    @Override
126    public boolean logout() throws LoginException {
127        subject.getPrincipals().removeAll(principals);
128
129        if (debug) {
130            LOG.debug("logout");
131        }
132        return true;
133    }
134}