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 }