/* * Copyright (c) 2004, 2008, 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 * particular file as subject to the "Classpath" exception as provided * by Oracle in the LICENSE file that accompanied this code. * * This code 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 General Public License * version 2 for more details (a copy is included in the LICENSE file that * accompanied this code). * * You should have received a copy of the GNU General Public License version * 2 along with this work; if not, write to the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. * * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA * or visit www.oracle.com if you need additional information or have any * questions. */ package com.sun.jmx.remote.security; import java.io.IOException; import java.security.AccessController; import java.security.Principal; import java.security.PrivilegedAction; import java.security.PrivilegedActionException; import java.security.PrivilegedExceptionAction; import java.util.Collections; import java.util.HashMap; import java.util.Map; import java.util.Properties; import javax.management.remote.JMXPrincipal; import javax.management.remote.JMXAuthenticator; import javax.security.auth.AuthPermission; import javax.security.auth.Subject; import javax.security.auth.callback.*; import javax.security.auth.login.AppConfigurationEntry; import javax.security.auth.login.Configuration; import javax.security.auth.login.LoginContext; import javax.security.auth.login.LoginException; import javax.security.auth.spi.LoginModule; import com.sun.jmx.remote.util.ClassLogger; import com.sun.jmx.remote.util.EnvHelp; /** *
This class represents a * JAAS * based implementation of the {@link JMXAuthenticator} interface.
* *Authentication is performed by passing the supplied user's credentials
* to one or more authentication mechanisms ({@link LoginModule}) for
* verification. An authentication mechanism acquires the user's credentials
* by calling {@link NameCallback} and/or {@link PasswordCallback}.
* If authentication is successful then an authenticated {@link Subject}
* filled in with a {@link Principal} is returned. Authorization checks
* will then be performed based on this Subject
.
By default, a single file-based authentication mechanism
* {@link FileLoginModule} is configured (FileLoginConfig
).
To override the default configuration use the
* com.sun.management.jmxremote.login.config
management property
* described in the JRE/lib/management/management.properties file.
* Set this property to the name of a JAAS configuration entry and ensure that
* the entry is loaded by the installed {@link Configuration}. In addition,
* ensure that the authentication mechanisms specified in the entry acquire
* the user's credentials by calling {@link NameCallback} and
* {@link PasswordCallback} and that they return a {@link Subject} filled-in
* with a {@link Principal}, for those users that are successfully
* authenticated.
JMXPluggableAuthenticator
* and initializes it with a {@link LoginContext}.
*
* @param env the environment containing configuration properties for the
* authenticator. Can be null, which is equivalent to an empty
* Map.
* @exception SecurityException if the authentication mechanism cannot be
* initialized.
*/
public JMXPluggableAuthenticator(Map, ?> env) {
String loginConfigName = null;
String passwordFile = null;
if (env != null) {
loginConfigName = (String) env.get(LOGIN_CONFIG_PROP);
passwordFile = (String) env.get(PASSWORD_FILE_PROP);
}
try {
if (loginConfigName != null) {
// use the supplied JAAS login configuration
loginContext =
new LoginContext(loginConfigName, new JMXCallbackHandler());
} else {
// use the default JAAS login configuration (file-based)
SecurityManager sm = System.getSecurityManager();
if (sm != null) {
sm.checkPermission(
new AuthPermission("createLoginContext." +
LOGIN_CONFIG_NAME));
}
final String pf = passwordFile;
try {
loginContext = AccessController.doPrivileged(
new PrivilegedExceptionActionMBeanServerConnection
client
* with the given client credentials.
*
* @param credentials the user-defined credentials to be passed in
* to the server in order to authenticate the user before creating
* the MBeanServerConnection
. This parameter must
* be a two-element String[]
containing the client's
* username and password in that order.
*
* @return the authenticated subject containing a
* JMXPrincipal(username)
.
*
* @exception SecurityException if the server cannot authenticate the user
* with the provided credentials.
*/
public Subject authenticate(Object credentials) {
// Verify that credentials is of type String[].
//
if (!(credentials instanceof String[])) {
// Special case for null so we get a more informative message
if (credentials == null)
authenticationFailure("authenticate", "Credentials required");
final String message =
"Credentials should be String[] instead of " +
credentials.getClass().getName();
authenticationFailure("authenticate", message);
}
// Verify that the array contains two elements.
//
final String[] aCredentials = (String[]) credentials;
if (aCredentials.length != 2) {
final String message =
"Credentials should have 2 elements not " +
aCredentials.length;
authenticationFailure("authenticate", message);
}
// Verify that username exists and the associated
// password matches the one supplied by the client.
//
username = aCredentials[0];
password = aCredentials[1];
if (username == null || password == null) {
final String message = "Username or password is null";
authenticationFailure("authenticate", message);
}
// Perform authentication
try {
loginContext.login();
final Subject subject = loginContext.getSubject();
AccessController.doPrivileged(new PrivilegedAction* JMXPluggableAuthenticator { * com.sun.jmx.remote.security.FileLoginModule required; * }; **/ private static class FileLoginConfig extends Configuration { // The JAAS configuration for file-based authentication private AppConfigurationEntry[] entries; // The classname of the login module for file-based authentication private static final String FILE_LOGIN_MODULE = FileLoginModule.class.getName(); // The option that identifies the password file to use private static final String PASSWORD_FILE_OPTION = "passwordFile"; /** * Creates an instance of
FileLoginConfig
*
* @param passwordFile A filepath that identifies the password file to use.
* If null then the default password file is used.
*/
public FileLoginConfig(String passwordFile) {
Map