< prev index next >

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

Print this page


   1 /*
   2  * Copyright (c) 2004, 2008, Oracle and/or its affiliates. All rights reserved.
   3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   4  *
   5  * This code is free software; you can redistribute it and/or modify it
   6  * under the terms of the GNU General Public License version 2 only, as
   7  * published by the Free Software Foundation.  Oracle designates this
   8  * particular file as subject to the "Classpath" exception as provided
   9  * by Oracle in the LICENSE file that accompanied this code.
  10  *
  11  * This code is distributed in the hope that it will be useful, but WITHOUT
  12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  14  * version 2 for more details (a copy is included in the LICENSE file that
  15  * accompanied this code).
  16  *
  17  * You should have received a copy of the GNU General Public License version
  18  * 2 along with this work; if not, write to the Free Software Foundation,
  19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  20  *
  21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  22  * or visit www.oracle.com if you need additional information or have any
  23  * questions.
  24  */
  25 
  26 package com.sun.jmx.remote.security;
  27 
  28 import java.io.IOException;
  29 import java.security.AccessController;
  30 import java.security.Principal;
  31 import java.security.PrivilegedAction;
  32 import java.security.PrivilegedActionException;
  33 import java.security.PrivilegedExceptionAction;
  34 import java.util.Collections;
  35 import java.util.HashMap;
  36 import java.util.Map;
  37 import java.util.Properties;
  38 import javax.management.remote.JMXPrincipal;
  39 import javax.management.remote.JMXAuthenticator;
  40 import javax.security.auth.AuthPermission;
  41 import javax.security.auth.Subject;
  42 import javax.security.auth.callback.*;
  43 import javax.security.auth.login.AppConfigurationEntry;
  44 import javax.security.auth.login.Configuration;
  45 import javax.security.auth.login.LoginContext;
  46 import javax.security.auth.login.LoginException;
  47 import javax.security.auth.spi.LoginModule;
  48 import com.sun.jmx.remote.util.ClassLogger;
  49 import com.sun.jmx.remote.util.EnvHelp;
  50 
  51 /**
  52  * <p>This class represents a
  53  * <a href="{@docRoot}/../guide/security/jaas/JAASRefGuide.html">JAAS</a>
  54  * based implementation of the {@link JMXAuthenticator} interface.</p>
  55  *
  56  * <p>Authentication is performed by passing the supplied user's credentials
  57  * to one or more authentication mechanisms ({@link LoginModule}) for
  58  * verification. An authentication mechanism acquires the user's credentials


  74  * {@link PasswordCallback} and that they return a {@link Subject} filled-in
  75  * with a {@link Principal}, for those users that are successfully
  76  * authenticated.</p>
  77  */
  78 public final class JMXPluggableAuthenticator implements JMXAuthenticator {
  79 
  80     /**
  81      * Creates an instance of <code>JMXPluggableAuthenticator</code>
  82      * and initializes it with a {@link LoginContext}.
  83      *
  84      * @param env the environment containing configuration properties for the
  85      *            authenticator. Can be null, which is equivalent to an empty
  86      *            Map.
  87      * @exception SecurityException if the authentication mechanism cannot be
  88      *            initialized.
  89      */
  90     public JMXPluggableAuthenticator(Map<?, ?> env) {
  91 
  92         String loginConfigName = null;
  93         String passwordFile = null;

  94 
  95         if (env != null) {
  96             loginConfigName = (String) env.get(LOGIN_CONFIG_PROP);
  97             passwordFile = (String) env.get(PASSWORD_FILE_PROP);

  98         }
  99 
 100         try {
 101 
 102             if (loginConfigName != null) {
 103                 // use the supplied JAAS login configuration
 104                 loginContext =
 105                     new LoginContext(loginConfigName, new JMXCallbackHandler());
 106 
 107             } else {
 108                 // use the default JAAS login configuration (file-based)
 109                 SecurityManager sm = System.getSecurityManager();
 110                 if (sm != null) {
 111                     sm.checkPermission(
 112                             new AuthPermission("createLoginContext." +
 113                                                LOGIN_CONFIG_NAME));
 114                 }
 115 
 116                 final String pf = passwordFile;

 117                 try {
 118                     loginContext = AccessController.doPrivileged(
 119                         new PrivilegedExceptionAction<LoginContext>() {
 120                             public LoginContext run() throws LoginException {
 121                                 return new LoginContext(
 122                                                 LOGIN_CONFIG_NAME,
 123                                                 null,
 124                                                 new JMXCallbackHandler(),
 125                                                 new FileLoginConfig(pf));
 126                             }
 127                         });
 128                 } catch (PrivilegedActionException pae) {
 129                     throw (LoginException) pae.getException();
 130                 }
 131             }
 132 
 133         } catch (LoginException le) {
 134             authenticationFailure("authenticate", le);
 135 
 136         } catch (SecurityException se) {
 137             authenticationFailure("authenticate", se);
 138         }
 139     }
 140 
 141     /**
 142      * Authenticate the <code>MBeanServerConnection</code> client
 143      * with the given client credentials.
 144      *
 145      * @param credentials the user-defined credentials to be passed in


 233 
 234     private static void logException(String method,
 235                                      String message,
 236                                      Exception e) {
 237         if (logger.traceOn()) {
 238             logger.trace(method, message);
 239         }
 240         if (logger.debugOn()) {
 241             logger.debug(method, e);
 242         }
 243     }
 244 
 245     private LoginContext loginContext;
 246     private String username;
 247     private String password;
 248     private static final String LOGIN_CONFIG_PROP =
 249         "jmx.remote.x.login.config";
 250     private static final String LOGIN_CONFIG_NAME = "JMXPluggableAuthenticator";
 251     private static final String PASSWORD_FILE_PROP =
 252         "jmx.remote.x.password.file";


 253     private static final ClassLogger logger =
 254         new ClassLogger("javax.management.remote.misc", LOGIN_CONFIG_NAME);
 255 
 256 /**
 257  * This callback handler supplies the username and password (which was
 258  * originally supplied by the JMX user) to the JAAS login module performing
 259  * the authentication. No interactive user prompting is required because the
 260  * credentials are already available to this class (via its enclosing class).
 261  */
 262 private final class JMXCallbackHandler implements CallbackHandler {
 263 
 264     /**
 265      * Sets the username and password in the appropriate Callback object.
 266      */
 267     public void handle(Callback[] callbacks)
 268         throws IOException, UnsupportedCallbackException {
 269 
 270         for (int i = 0; i < callbacks.length; i++) {
 271             if (callbacks[i] instanceof NameCallback) {
 272                 ((NameCallback)callbacks[i]).setName(username);


 286 /**
 287  * This class defines the JAAS configuration for file-based authentication.
 288  * It is equivalent to the following textual configuration entry:
 289  * <pre>
 290  *     JMXPluggableAuthenticator {
 291  *         com.sun.jmx.remote.security.FileLoginModule required;
 292  *     };
 293  * </pre>
 294  */
 295 private static class FileLoginConfig extends Configuration {
 296 
 297     // The JAAS configuration for file-based authentication
 298     private AppConfigurationEntry[] entries;
 299 
 300     // The classname of the login module for file-based authentication
 301     private static final String FILE_LOGIN_MODULE =
 302         FileLoginModule.class.getName();
 303 
 304     // The option that identifies the password file to use
 305     private static final String PASSWORD_FILE_OPTION = "passwordFile";

 306 
 307     /**
 308      * Creates an instance of <code>FileLoginConfig</code>
 309      *
 310      * @param passwordFile A filepath that identifies the password file to use.
 311      *                     If null then the default password file is used.

 312      */
 313     public FileLoginConfig(String passwordFile) {
 314 
 315         Map<String, String> options;
 316         if (passwordFile != null) {
 317             options = new HashMap<String, String>(1);
 318             options.put(PASSWORD_FILE_OPTION, passwordFile);

 319         } else {
 320             options = Collections.emptyMap();
 321         }
 322 
 323         entries = new AppConfigurationEntry[] {
 324             new AppConfigurationEntry(FILE_LOGIN_MODULE,
 325                 AppConfigurationEntry.LoginModuleControlFlag.REQUIRED,
 326                     options)
 327         };
 328     }
 329 
 330     /**
 331      * Gets the JAAS configuration for file-based authentication
 332      */
 333     public AppConfigurationEntry[] getAppConfigurationEntry(String name) {
 334 
 335         return name.equals(LOGIN_CONFIG_NAME) ? entries : null;
 336     }
 337 
 338     /**
   1 /*
   2  * Copyright (c) 2004, 2017, Oracle and/or its affiliates. All rights reserved.
   3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   4  *
   5  * This code is free software; you can redistribute it and/or modify it
   6  * under the terms of the GNU General Public License version 2 only, as
   7  * published by the Free Software Foundation.  Oracle designates this
   8  * particular file as subject to the "Classpath" exception as provided
   9  * by Oracle in the LICENSE file that accompanied this code.
  10  *
  11  * This code is distributed in the hope that it will be useful, but WITHOUT
  12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  14  * version 2 for more details (a copy is included in the LICENSE file that
  15  * accompanied this code).
  16  *
  17  * You should have received a copy of the GNU General Public License version
  18  * 2 along with this work; if not, write to the Free Software Foundation,
  19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  20  *
  21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  22  * or visit www.oracle.com if you need additional information or have any
  23  * questions.
  24  */
  25 
  26 package com.sun.jmx.remote.security;
  27 
  28 import java.io.IOException;
  29 import java.security.AccessController;
  30 import java.security.Principal;
  31 import java.security.PrivilegedAction;
  32 import java.security.PrivilegedActionException;
  33 import java.security.PrivilegedExceptionAction;
  34 import java.util.Collections;
  35 import java.util.HashMap;
  36 import java.util.Map;


  37 import javax.management.remote.JMXAuthenticator;
  38 import javax.security.auth.AuthPermission;
  39 import javax.security.auth.Subject;
  40 import javax.security.auth.callback.*;
  41 import javax.security.auth.login.AppConfigurationEntry;
  42 import javax.security.auth.login.Configuration;
  43 import javax.security.auth.login.LoginContext;
  44 import javax.security.auth.login.LoginException;
  45 import javax.security.auth.spi.LoginModule;
  46 import com.sun.jmx.remote.util.ClassLogger;
  47 import com.sun.jmx.remote.util.EnvHelp;
  48 
  49 /**
  50  * <p>This class represents a
  51  * <a href="{@docRoot}/../guide/security/jaas/JAASRefGuide.html">JAAS</a>
  52  * based implementation of the {@link JMXAuthenticator} interface.</p>
  53  *
  54  * <p>Authentication is performed by passing the supplied user's credentials
  55  * to one or more authentication mechanisms ({@link LoginModule}) for
  56  * verification. An authentication mechanism acquires the user's credentials


  72  * {@link PasswordCallback} and that they return a {@link Subject} filled-in
  73  * with a {@link Principal}, for those users that are successfully
  74  * authenticated.</p>
  75  */
  76 public final class JMXPluggableAuthenticator implements JMXAuthenticator {
  77 
  78     /**
  79      * Creates an instance of <code>JMXPluggableAuthenticator</code>
  80      * and initializes it with a {@link LoginContext}.
  81      *
  82      * @param env the environment containing configuration properties for the
  83      *            authenticator. Can be null, which is equivalent to an empty
  84      *            Map.
  85      * @exception SecurityException if the authentication mechanism cannot be
  86      *            initialized.
  87      */
  88     public JMXPluggableAuthenticator(Map<?, ?> env) {
  89 
  90         String loginConfigName = null;
  91         String passwordFile = null;
  92         String hashPasswords = null;
  93 
  94         if (env != null) {
  95             loginConfigName = (String) env.get(LOGIN_CONFIG_PROP);
  96             passwordFile = (String) env.get(PASSWORD_FILE_PROP);
  97             hashPasswords = (String) env.get(HASH_PASSWORDS);
  98         }
  99 
 100         try {
 101 
 102             if (loginConfigName != null) {
 103                 // use the supplied JAAS login configuration
 104                 loginContext =
 105                     new LoginContext(loginConfigName, new JMXCallbackHandler());
 106 
 107             } else {
 108                 // use the default JAAS login configuration (file-based)
 109                 SecurityManager sm = System.getSecurityManager();
 110                 if (sm != null) {
 111                     sm.checkPermission(
 112                             new AuthPermission("createLoginContext." +
 113                                                LOGIN_CONFIG_NAME));
 114                 }
 115 
 116                 final String pf = passwordFile;
 117                 final String hashPass = hashPasswords;
 118                 try {
 119                     loginContext = AccessController.doPrivileged(
 120                         new PrivilegedExceptionAction<LoginContext>() {
 121                             public LoginContext run() throws LoginException {
 122                                 return new LoginContext(
 123                                                 LOGIN_CONFIG_NAME,
 124                                                 null,
 125                                                 new JMXCallbackHandler(),
 126                                                 new FileLoginConfig(pf, hashPass));
 127                             }
 128                         });
 129                 } catch (PrivilegedActionException pae) {
 130                     throw (LoginException) pae.getException();
 131                 }
 132             }
 133 
 134         } catch (LoginException le) {
 135             authenticationFailure("authenticate", le);
 136 
 137         } catch (SecurityException se) {
 138             authenticationFailure("authenticate", se);
 139         }
 140     }
 141 
 142     /**
 143      * Authenticate the <code>MBeanServerConnection</code> client
 144      * with the given client credentials.
 145      *
 146      * @param credentials the user-defined credentials to be passed in


 234 
 235     private static void logException(String method,
 236                                      String message,
 237                                      Exception e) {
 238         if (logger.traceOn()) {
 239             logger.trace(method, message);
 240         }
 241         if (logger.debugOn()) {
 242             logger.debug(method, e);
 243         }
 244     }
 245 
 246     private LoginContext loginContext;
 247     private String username;
 248     private String password;
 249     private static final String LOGIN_CONFIG_PROP =
 250         "jmx.remote.x.login.config";
 251     private static final String LOGIN_CONFIG_NAME = "JMXPluggableAuthenticator";
 252     private static final String PASSWORD_FILE_PROP =
 253         "jmx.remote.x.password.file";
 254     private static final String HASH_PASSWORDS =
 255         "jmx.remote.x.password.hashpasswords";
 256     private static final ClassLogger logger =
 257         new ClassLogger("javax.management.remote.misc", LOGIN_CONFIG_NAME);
 258 
 259 /**
 260  * This callback handler supplies the username and password (which was
 261  * originally supplied by the JMX user) to the JAAS login module performing
 262  * the authentication. No interactive user prompting is required because the
 263  * credentials are already available to this class (via its enclosing class).
 264  */
 265 private final class JMXCallbackHandler implements CallbackHandler {
 266 
 267     /**
 268      * Sets the username and password in the appropriate Callback object.
 269      */
 270     public void handle(Callback[] callbacks)
 271         throws IOException, UnsupportedCallbackException {
 272 
 273         for (int i = 0; i < callbacks.length; i++) {
 274             if (callbacks[i] instanceof NameCallback) {
 275                 ((NameCallback)callbacks[i]).setName(username);


 289 /**
 290  * This class defines the JAAS configuration for file-based authentication.
 291  * It is equivalent to the following textual configuration entry:
 292  * <pre>
 293  *     JMXPluggableAuthenticator {
 294  *         com.sun.jmx.remote.security.FileLoginModule required;
 295  *     };
 296  * </pre>
 297  */
 298 private static class FileLoginConfig extends Configuration {
 299 
 300     // The JAAS configuration for file-based authentication
 301     private AppConfigurationEntry[] entries;
 302 
 303     // The classname of the login module for file-based authentication
 304     private static final String FILE_LOGIN_MODULE =
 305         FileLoginModule.class.getName();
 306 
 307     // The option that identifies the password file to use
 308     private static final String PASSWORD_FILE_OPTION = "passwordFile";
 309     private static final String HASH_PASSWORDS = "hashPasswords";
 310 
 311     /**
 312      * Creates an instance of <code>FileLoginConfig</code>
 313      *
 314      * @param passwordFile A filepath that identifies the password file to use.
 315      *                     If null then the default password file is used.
 316      * @param hashPasswords Flag to indicate if password file needs to be hashed
 317      */
 318     public FileLoginConfig(String passwordFile, String hashPasswords) {
 319 
 320         Map<String, String> options;
 321         if (passwordFile != null) {
 322             options = new HashMap<String, String>(1);
 323             options.put(PASSWORD_FILE_OPTION, passwordFile);
 324             options.put(HASH_PASSWORDS, hashPasswords);
 325         } else {
 326             options = Collections.emptyMap();
 327         }
 328 
 329         entries = new AppConfigurationEntry[] {
 330             new AppConfigurationEntry(FILE_LOGIN_MODULE,
 331                 AppConfigurationEntry.LoginModuleControlFlag.REQUIRED,
 332                     options)
 333         };
 334     }
 335 
 336     /**
 337      * Gets the JAAS configuration for file-based authentication
 338      */
 339     public AppConfigurationEntry[] getAppConfigurationEntry(String name) {
 340 
 341         return name.equals(LOGIN_CONFIG_NAME) ? entries : null;
 342     }
 343 
 344     /**
< prev index next >