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 }