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    package org.apache.activemq.jaas;
018    
019    import java.io.File;
020    import java.io.IOException;
021    import java.security.Principal;
022    import java.util.Enumeration;
023    import java.util.HashSet;
024    import java.util.Map;
025    import java.util.Properties;
026    import java.util.Set;
027    
028    import javax.security.auth.Subject;
029    import javax.security.auth.callback.Callback;
030    import javax.security.auth.callback.CallbackHandler;
031    import javax.security.auth.callback.NameCallback;
032    import javax.security.auth.callback.PasswordCallback;
033    import javax.security.auth.callback.UnsupportedCallbackException;
034    import javax.security.auth.login.FailedLoginException;
035    import javax.security.auth.login.LoginException;
036    import javax.security.auth.spi.LoginModule;
037    
038    import org.apache.commons.logging.Log;
039    import org.apache.commons.logging.LogFactory;
040    
041    /**
042     * @version $Rev: $ $Date: $
043     */
044    public class PropertiesLoginModule implements LoginModule {
045    
046        private static final String USER_FILE = "org.apache.activemq.jaas.properties.user";
047        private static final String GROUP_FILE = "org.apache.activemq.jaas.properties.group";
048    
049        private static final Log LOG = LogFactory.getLog(PropertiesLoginModule.class);
050    
051        private Subject subject;
052        private CallbackHandler callbackHandler;
053    
054        private boolean debug;
055        private String usersFile;
056        private String groupsFile;
057        private Properties users = new Properties();
058        private Properties groups = new Properties();
059        private String user;
060        private Set<Principal> principals = new HashSet<Principal>();
061        private File baseDir;
062    
063        public void initialize(Subject subject, CallbackHandler callbackHandler, Map sharedState, Map options) {
064            this.subject = subject;
065            this.callbackHandler = callbackHandler;
066    
067            if (System.getProperty("java.security.auth.login.config") != null) {
068                baseDir = new File(System.getProperty("java.security.auth.login.config")).getParentFile();
069            } else {
070                baseDir = new File(".");
071            }
072    
073            debug = "true".equalsIgnoreCase((String)options.get("debug"));
074            usersFile = (String)options.get(USER_FILE) + "";
075            groupsFile = (String)options.get(GROUP_FILE) + "";
076    
077            if (debug) {
078                LOG.debug("Initialized debug=" + debug + " usersFile=" + usersFile + " groupsFile=" + groupsFile + " basedir=" + baseDir);
079            }
080        }
081    
082        public boolean login() throws LoginException {
083            File f = new File(baseDir, usersFile);
084            try {
085                java.io.FileInputStream in = new java.io.FileInputStream(f);
086                users.load(in);
087                in.close();
088            } catch (IOException ioe) {
089                throw new LoginException("Unable to load user properties file " + f);
090            }
091            f = new File(baseDir, groupsFile);
092            try {
093                java.io.FileInputStream in = new java.io.FileInputStream(f);
094                groups.load(in);
095                in.close();
096            } catch (IOException ioe) {
097                throw new LoginException("Unable to load group properties file " + f);
098            }
099    
100            Callback[] callbacks = new Callback[2];
101    
102            callbacks[0] = new NameCallback("Username: ");
103            callbacks[1] = new PasswordCallback("Password: ", false);
104            try {
105                callbackHandler.handle(callbacks);
106            } catch (IOException ioe) {
107                throw new LoginException(ioe.getMessage());
108            } catch (UnsupportedCallbackException uce) {
109                throw new LoginException(uce.getMessage() + " not available to obtain information from user");
110            }
111            user = ((NameCallback)callbacks[0]).getName();
112            char[] tmpPassword = ((PasswordCallback)callbacks[1]).getPassword();
113            if (tmpPassword == null) {
114                tmpPassword = new char[0];
115            }
116            String password = users.getProperty(user);
117    
118            if (password == null) {
119                throw new FailedLoginException("User does exist");
120            }
121            if (!password.equals(new String(tmpPassword))) {
122                throw new FailedLoginException("Password does not match");
123            }
124            users.clear();
125    
126            if (debug) {
127                LOG.debug("login " + user);
128            }
129            return true;
130        }
131    
132        public boolean commit() throws LoginException {
133            principals.add(new UserPrincipal(user));
134    
135            for (Enumeration enumeration = groups.keys(); enumeration.hasMoreElements();) {
136                String name = (String)enumeration.nextElement();
137                String[] userList = ((String)groups.getProperty(name) + "").split(",");
138                for (int i = 0; i < userList.length; i++) {
139                    if (user.equals(userList[i])) {
140                        principals.add(new GroupPrincipal(name));
141                        break;
142                    }
143                }
144            }
145    
146            subject.getPrincipals().addAll(principals);
147    
148            clear();
149    
150            if (debug) {
151                LOG.debug("commit");
152            }
153            return true;
154        }
155    
156        public boolean abort() throws LoginException {
157            clear();
158    
159            if (debug) {
160                LOG.debug("abort");
161            }
162            return true;
163        }
164    
165        public boolean logout() throws LoginException {
166            subject.getPrincipals().removeAll(principals);
167            principals.clear();
168    
169            if (debug) {
170                LOG.debug("logout");
171            }
172            return true;
173        }
174    
175        private void clear() {
176            groups.clear();
177            user = null;
178        }
179    }