/* * JBoss, Home of Professional Open Source. * Copyright 2008, Red Hat Middleware LLC, and individual contributors * as indicated by the @author tags. See the copyright.txt file in the * distribution for a full listing of individual contributors. * * This is free software; you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License as * published by the Free Software Foundation; either version 2.1 of * the License, or (at your option) any later version. * * This software is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this software; if not, write to the Free * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA * 02110-1301 USA, or see the FSF site: http://www.fsf.org. */ package org.jboss.test.security.service; import java.io.FileNotFoundException; import java.io.InputStream; import java.io.IOException; import java.math.BigInteger; import java.net.URL; import java.security.KeyException; import java.util.HashMap; import java.util.Iterator; import java.util.Properties; import javax.naming.InitialContext; import javax.naming.Name; import org.jboss.naming.NonSerializableFactory; import org.jboss.crypto.CryptoUtil; import org.jboss.security.srp.SRPConf; import org.jboss.security.srp.SRPVerifierStore; import org.jboss.security.srp.SRPVerifierStore.VerifierInfo; import org.jboss.system.ServiceMBeanSupport; /** The PropertiesVerifierStore service is a SRPVerifierStore implementation that obtains the username and password info from a properties file and then creates an in memory SRPVerifierStore. @author Scott.Stark@jboss.org @version $Revision: 81036 $ */ public class PropertiesVerifierStore extends ServiceMBeanSupport implements PropertiesVerifierStoreMBean, SRPVerifierStore { private String jndiName = "srp/DefaultVerifierSource"; private HashMap storeMap = new HashMap(); private Thread addUserThread; /** Creates a new instance of PropertiesVerifierStore */ public PropertiesVerifierStore() { } /** Get the jndi name for the SRPVerifierSource implementation binding. */ public String getJndiName() { return jndiName; } /** set the jndi name for the SRPVerifierSource implementation binding. */ public void setJndiName(String jndiName) { this.jndiName = jndiName; } protected void startService() throws Exception { // Make sure the security utility class is initialized CryptoUtil.init(); // Find the users.properties file ClassLoader loader = Thread.currentThread().getContextClassLoader(); URL users = loader.getResource("users.properties"); if( users == null ) throw new FileNotFoundException("Failed to find users.properties resource"); InputStream is = users.openStream(); final Properties userPasswords = new Properties(); userPasswords.load(is); is.close(); addUserThread = new Thread("AddUsers") { public void run() { Iterator keys = userPasswords.keySet().iterator(); while( keys.hasNext() ) { String username = (String) keys.next(); char[] password = userPasswords.getProperty(username).toCharArray(); String cipherAlgorithm = "Blowfish"; String hashAlgorithm = "SHA_Interleave"; addUser(username, password, cipherAlgorithm, hashAlgorithm); log.info("Added user: "+username); } } }; addUserThread.start(); // Bind a reference to the SRPVerifierStore using NonSerializableFactory InitialContext ctx = new InitialContext(); Name name = ctx.getNameParser("").parse(jndiName); NonSerializableFactory.rebind(name, this, true); log.debug("Bound SRPVerifierStore at "+jndiName); } protected void stopService() throws Exception { InitialContext ctx = new InitialContext(); NonSerializableFactory.unbind(jndiName); ctx.unbind(jndiName); log.debug("Unbound SRPVerifierStore at "+jndiName); } public VerifierInfo getUserVerifier(String username) throws KeyException, IOException { if( addUserThread != null ) { try { addUserThread.join(); addUserThread = null; } catch(InterruptedException e) { } } VerifierInfo info = (VerifierInfo) storeMap.get(username); return info; } public void setUserVerifier(String username, VerifierInfo info) throws IOException { throw new IOException("PropertiesVerifierStore is read only"); } public void verifyUserChallenge(String username, Object auxChallenge) throws SecurityException { } private void addUser(String username, char[] password, String cipherAlgorithm, String hashAlgorithm) { VerifierInfo info = new VerifierInfo(); info.username = username; // Create a random salt long r = CryptoUtil.nextLong(); String rs = Long.toHexString(r); info.salt = rs.getBytes(); BigInteger g = SRPConf.getDefaultParams().g(); BigInteger N = SRPConf.getDefaultParams().N(); info.cipherAlgorithm = cipherAlgorithm; info.hashAlgorithm = hashAlgorithm; info.verifier = CryptoUtil.calculateVerifier(username, password, info.salt, N, g); info.g = g.toByteArray(); info.N = N.toByteArray(); storeMap.put(username, info); } }