< prev index next >

src/java.management/share/classes/com/sun/jmx/remote/security/FileLoginModule.java

Print this page

        

@@ -1,7 +1,7 @@
 /*
- * Copyright (c) 2004, 2008, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2004, 2017, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
  * under the terms of the GNU General Public License version 2 only, as
  * published by the Free Software Foundation.  Oracle designates this

@@ -25,21 +25,17 @@
 
 package com.sun.jmx.remote.security;
 
 import com.sun.jmx.mbeanserver.GetPropertyAction;
 import com.sun.jmx.mbeanserver.Util;
-import java.io.BufferedInputStream;
 import java.io.File;
-import java.io.FileInputStream;
 import java.io.FilePermission;
 import java.io.IOException;
 import java.security.AccessControlException;
 import java.security.AccessController;
 import java.util.Arrays;
-import java.util.Hashtable;
 import java.util.Map;
-import java.util.Properties;
 
 import javax.security.auth.*;
 import javax.security.auth.callback.*;
 import javax.security.auth.login.*;
 import javax.security.auth.spi.*;

@@ -57,14 +53,11 @@
  * user's name and it is associated with the current {@link Subject}.
  * Such principals may be identified and granted management privileges in
  * the access control file for JMX remote management or in a Java security
  * policy.
  *
- * <p> The password file comprises a list of key-value pairs as specified in
- * {@link Properties}. The key represents a user's name and the value is its
- * associated cleartext password. By default, the following password file is
- * used:
+ * By default, the following password file is used:
  * <pre>
  *     ${java.home}/conf/management/jmxremote.password
  * </pre>
  * A different password file can be specified via the <code>passwordFile</code>
  * configuration option.

@@ -103,10 +96,15 @@
  *
  * <dt> <code>clearPass</code> </dt>
  * <dd> if <code>true</code>, this module clears the username and password
  *      stored in the module's shared state after both phases of authentication
  *      (login and commit) have completed.</dd>
+ *
+ * <dt> <code>hashPasswords</code> </dt>
+ * <dd> if <code>true</code>, this module replaces each clear text passwords
+ *      with its hash, if present. </dd>
+ *
  * </dl>
  */
 public class FileLoginModule implements LoginModule {
 
     private static final String PASSWORD_FILE_NAME = "jmxremote.password";

@@ -133,10 +131,11 @@
     // Configurable options
     private boolean useFirstPass = false;
     private boolean tryFirstPass = false;
     private boolean storePass = false;
     private boolean clearPass = false;
+    private boolean hashPasswords = false;
 
     // Authentication status
     private boolean succeeded = false;
     private boolean commitSucceeded = false;
 

@@ -152,11 +151,11 @@
     private Map<String, ?> options;
     private String passwordFile;
     private String passwordFileDisplayName;
     private boolean userSuppliedPasswordFile;
     private boolean hasJavaHomePermission;
-    private Properties userCredentials;
+    private HashedPasswordManager hashPwdMgr;
 
     /**
      * Initialize this <code>LoginModule</code>.
      *
      * @param subject the <code>Subject</code> to be authenticated.

@@ -184,10 +183,12 @@
                 "true".equalsIgnoreCase((String)options.get("useFirstPass"));
         storePass =
                 "true".equalsIgnoreCase((String)options.get("storePass"));
         clearPass =
                 "true".equalsIgnoreCase((String)options.get("clearPass"));
+        hashPasswords =
+                "true".equalsIgnoreCase((String)options.get("hashPasswords"));
 
         passwordFile = (String)options.get("passwordFile");
         passwordFileDisplayName = passwordFile;
         userSuppliedPasswordFile = true;
 

@@ -219,21 +220,31 @@
      *          is unable to perform the authentication.
      */
     public boolean login() throws LoginException {
 
         try {
-            loadPasswordFile();
+            if(hashPwdMgr == null) {
+                hashPwdMgr = new HashedPasswordManager(passwordFile, hashPasswords);
+            } else {
+                hashPwdMgr.loadPasswords();
+            }
         } catch (IOException ioe) {
             LoginException le = new LoginException(
                     "Error: unable to load the password file: " +
                     passwordFileDisplayName);
             throw EnvHelp.initCause(le, ioe);
+        } catch (SecurityException e) {
+            if (userSuppliedPasswordFile || hasJavaHomePermission) {
+                throw e;
+            } else {
+                final FilePermission fp =
+                        new FilePermission(passwordFileDisplayName, "read");
+                AccessControlException ace = new AccessControlException(
+                        "access denied " + fp.toString());
+                ace.setStackTrace(e.getStackTrace());
+                throw ace;
         }
-
-        if (userCredentials == null) {
-            throw new LoginException
-                ("Error: unable to locate the users' credentials.");
         }
 
         if (logger.debugOn()) {
             logger.debug("login",
                     "Using password file: " + passwordFileDisplayName);

@@ -435,16 +446,11 @@
         throws LoginException {
 
         // get the username and password
         getUsernamePassword(usePasswdFromSharedState);
 
-        String localPassword;
-
-        // userCredentials is initialized in login()
-        if (((localPassword = userCredentials.getProperty(username)) == null) ||
-            (! localPassword.equals(new String(password)))) {
-
+        if (!hashPwdMgr.authenticate(username, new String(password))) {
             // username not found or passwords do not match
             if (logger.debugOn()) {
                 logger.debug("login", "Invalid username or password");
             }
             throw new FailedLoginException("Invalid username or password");

@@ -466,42 +472,10 @@
             logger.debug("login",
                 "User '" + username + "' successfully validated");
         }
     }
 
-    /*
-     * Read the password file.
-     */
-    private void loadPasswordFile() throws IOException {
-        FileInputStream fis;
-        try {
-            fis = new FileInputStream(passwordFile);
-        } catch (SecurityException e) {
-            if (userSuppliedPasswordFile || hasJavaHomePermission) {
-                throw e;
-            } else {
-                final FilePermission fp =
-                        new FilePermission(passwordFileDisplayName, "read");
-                AccessControlException ace = new AccessControlException(
-                        "access denied " + fp.toString());
-                ace.setStackTrace(e.getStackTrace());
-                throw ace;
-            }
-        }
-        try {
-            final BufferedInputStream bis = new BufferedInputStream(fis);
-            try {
-                userCredentials = new Properties();
-                userCredentials.load(bis);
-            } finally {
-                bis.close();
-            }
-        } finally {
-            fis.close();
-        }
-    }
-
     /**
      * Get the username and password.
      * This method does not return any value.
      * Instead, it sets global name and password variables.
      *
< prev index next >