/** Generate a local password and save it in the local-password file. */ public void postConstruct() { logger.fine("Generating local password"); SecureRandom random = new SecureRandom(); byte[] pwd = new byte[PASSWORD_BYTES]; random.nextBytes(pwd); password = toHex(pwd); File localPasswordFile = new File(env.getConfigDirPath(), LOCAL_PASSWORD_FILE); PrintWriter w = null; try { if (!localPasswordFile.exists()) { localPasswordFile.createNewFile(); /* * XXX - There's a security hole here. * Between the time the file is created and the permissions * are changed to prevent others from opening it, someone * else could open it and wait for the data to be written. * Java needs the ability to create a file that's readable * only by the owner; coming in JDK 7. */ localPasswordFile.setWritable(false, false); // take from all localPasswordFile.setWritable(true, true); // owner only localPasswordFile.setReadable(false, false); // take from all localPasswordFile.setReadable(true, true); // owner only } w = new PrintWriter(localPasswordFile); w.println(password); } catch (IOException ex) { // ignore errors logger.log(Level.FINE, "Exception writing local password file", ex); } finally { if (w != null) w.close(); } }
/** * Manage a local password, which is a cryptographically secure random number stored in a file with * permissions that only allow the owner to read it. A new local password is generated each time the * server starts. The asadmin client can use it to authenticate when executing local commands, such * as stop-domain, without the user needing to supply a password. * * @author Bill Shannon */ @Service @Scoped(Singleton.class) // only want one local password public class LocalPasswordImpl implements PostConstruct, Init, LocalPassword { @Inject ServerEnvironment env; private String password; private static final String LOCAL_PASSWORD_FILE = "local-password"; private static final int PASSWORD_BYTES = 20; private static final char[] hex = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' }; private final Logger logger = Logger.getAnonymousLogger(); /** Generate a local password and save it in the local-password file. */ public void postConstruct() { logger.fine("Generating local password"); SecureRandom random = new SecureRandom(); byte[] pwd = new byte[PASSWORD_BYTES]; random.nextBytes(pwd); password = toHex(pwd); File localPasswordFile = new File(env.getConfigDirPath(), LOCAL_PASSWORD_FILE); PrintWriter w = null; try { if (!localPasswordFile.exists()) { localPasswordFile.createNewFile(); /* * XXX - There's a security hole here. * Between the time the file is created and the permissions * are changed to prevent others from opening it, someone * else could open it and wait for the data to be written. * Java needs the ability to create a file that's readable * only by the owner; coming in JDK 7. */ localPasswordFile.setWritable(false, false); // take from all localPasswordFile.setWritable(true, true); // owner only localPasswordFile.setReadable(false, false); // take from all localPasswordFile.setReadable(true, true); // owner only } w = new PrintWriter(localPasswordFile); w.println(password); } catch (IOException ex) { // ignore errors logger.log(Level.FINE, "Exception writing local password file", ex); } finally { if (w != null) w.close(); } } /** Is the given password the local password? */ public boolean isLocalPassword(String p) { return password != null && password.equals(p); } /** Get the local password. */ public String getLocalPassword() { return password; } /** Convert the byte array to a hex string. */ private static String toHex(byte[] b) { char[] bc = new char[b.length * 2]; for (int i = 0, j = 0; i < b.length; i++) { byte bb = b[i]; bc[j++] = hex[(bb >> 4) & 0xF]; bc[j++] = hex[bb & 0xF]; } return new String(bc); } }