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 private boolean loginSucceeded;
063
064 public void initialize(Subject subject, CallbackHandler callbackHandler, Map sharedState, Map options) {
065 this.subject = subject;
066 this.callbackHandler = callbackHandler;
067 loginSucceeded = false;
068
069 if (System.getProperty("java.security.auth.login.config") != null) {
070 baseDir = new File(System.getProperty("java.security.auth.login.config")).getParentFile();
071 } else {
072 baseDir = new File(".");
073 }
074
075 debug = "true".equalsIgnoreCase((String)options.get("debug"));
076 usersFile = (String)options.get(USER_FILE) + "";
077 groupsFile = (String)options.get(GROUP_FILE) + "";
078
079 if (debug) {
080 LOG.debug("Initialized debug=" + debug + " usersFile=" + usersFile + " groupsFile=" + groupsFile + " basedir=" + baseDir);
081 }
082 }
083
084 public boolean login() throws LoginException {
085 File f = new File(baseDir, usersFile);
086 try {
087 java.io.FileInputStream in = new java.io.FileInputStream(f);
088 users.load(in);
089 in.close();
090 } catch (IOException ioe) {
091 throw new LoginException("Unable to load user properties file " + f);
092 }
093 f = new File(baseDir, groupsFile);
094 try {
095 java.io.FileInputStream in = new java.io.FileInputStream(f);
096 groups.load(in);
097 in.close();
098 } catch (IOException ioe) {
099 throw new LoginException("Unable to load group properties file " + f);
100 }
101
102 Callback[] callbacks = new Callback[2];
103
104 callbacks[0] = new NameCallback("Username: ");
105 callbacks[1] = new PasswordCallback("Password: ", false);
106 try {
107 callbackHandler.handle(callbacks);
108 } catch (IOException ioe) {
109 throw new LoginException(ioe.getMessage());
110 } catch (UnsupportedCallbackException uce) {
111 throw new LoginException(uce.getMessage() + " not available to obtain information from user");
112 }
113 user = ((NameCallback)callbacks[0]).getName();
114 char[] tmpPassword = ((PasswordCallback)callbacks[1]).getPassword();
115 if (tmpPassword == null) {
116 tmpPassword = new char[0];
117 }
118 String password = users.getProperty(user);
119
120 if (password == null) {
121 throw new FailedLoginException("User does exist");
122 }
123 if (!password.equals(new String(tmpPassword))) {
124 throw new FailedLoginException("Password does not match");
125 }
126 loginSucceeded = true;
127 users.clear();
128
129 if (debug) {
130 LOG.debug("login " + user);
131 }
132 return loginSucceeded;
133 }
134
135 public boolean commit() throws LoginException {
136 boolean result = loginSucceeded;
137 if (result) {
138 principals.add(new UserPrincipal(user));
139
140 for (Enumeration enumeration = groups.keys(); enumeration.hasMoreElements();) {
141 String name = (String)enumeration.nextElement();
142 String[] userList = ((String)groups.getProperty(name) + "").split(",");
143 for (int i = 0; i < userList.length; i++) {
144 if (user.equals(userList[i])) {
145 principals.add(new GroupPrincipal(name));
146 break;
147 }
148 }
149 }
150
151 subject.getPrincipals().addAll(principals);
152 }
153
154 // will whack loginSucceeded
155 clear();
156
157 if (debug) {
158 LOG.debug("commit, result: " + result);
159 }
160 return result;
161 }
162
163 public boolean abort() throws LoginException {
164 clear();
165
166 if (debug) {
167 LOG.debug("abort");
168 }
169 return true;
170 }
171
172 public boolean logout() throws LoginException {
173 subject.getPrincipals().removeAll(principals);
174 principals.clear();
175 clear();
176 if (debug) {
177 LOG.debug("logout");
178 }
179 return true;
180 }
181
182 private void clear() {
183 groups.clear();
184 user = null;
185 loginSucceeded = false;
186 }
187 }