diff -r ee92e7cf8d35 -r f7bcbf987d5c jdk/src/share/classes/sun/security/provider/ConfigSpiFile.java --- a/jdk/src/share/classes/sun/security/provider/ConfigSpiFile.java Thu Aug 22 09:10:13 2013 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,693 +0,0 @@ -/* - * Copyright (c) 2000, 2012, 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 sun.security.provider; - -import java.io.*; -import java.net.MalformedURLException; -import java.net.URI; -import java.net.URL; -import java.security.AccessController; -import java.security.PrivilegedAction; -import java.security.PrivilegedActionException; -import java.security.PrivilegedExceptionAction; -import java.security.Security; -import java.security.URIParameter; -import java.text.MessageFormat; -import java.util.*; -import javax.security.auth.AuthPermission; -import javax.security.auth.login.AppConfigurationEntry; -import javax.security.auth.login.Configuration; -import javax.security.auth.login.ConfigurationSpi; -import sun.security.util.Debug; -import sun.security.util.PropertyExpander; -import sun.security.util.ResourcesMgr; - -/** - * This class represents a default implementation for - * {@code javax.security.auth.login.Configuration}. - * - *

This object stores the runtime login configuration representation, - * and is the amalgamation of multiple static login - * configurations that resides in files. - * The algorithm for locating the login configuration file(s) and reading their - * information into this {@code Configuration} object is: - * - *

    - *
  1. - * Loop through the security properties, - * login.config.url.1, login.config.url.2, ..., - * login.config.url.X. - * Each property value specifies a URL pointing to a - * login configuration file to be loaded. Read in and load - * each configuration. - * - *
  2. - * The {@code java.lang.System} property - * java.security.auth.login.config - * may also be set to a {@code URL} pointing to another - * login configuration file - * (which is the case when a user uses the -D switch at runtime). - * If this property is defined, and its use is allowed by the - * security property file (the Security property, - * policy.allowSystemProperty is set to true), - * also load that login configuration. - * - *
  3. - * If the java.security.auth.login.config property is defined using - * "==" (rather than "="), then ignore all other specified - * login configurations and only load this configuration. - * - *
  4. - * If no system or security properties were set, try to read from the file, - * ${user.home}/.java.login.config, where ${user.home} is the value - * represented by the "user.home" System property. - *
- * - *

The configuration syntax supported by this implementation - * is exactly that syntax specified in the - * {@code javax.security.auth.login.Configuration} class. - * - * @see javax.security.auth.login.LoginContext - * @see java.security.Security security properties - */ -public final class ConfigSpiFile extends ConfigurationSpi { - - private URL url; - private boolean expandProp = true; - private Map> configuration; - private int linenum; - private StreamTokenizer st; - private int lookahead; - - private static Debug debugConfig = Debug.getInstance("configfile"); - private static Debug debugParser = Debug.getInstance("configparser"); - - /** - * Create a new {@code Configuration} object. - * - * @throws SecurityException if the {@code Configuration} can not be - * initialized - */ - public ConfigSpiFile() { - try { - init(); - } catch (IOException ioe) { - throw new SecurityException(ioe); - } - } - - /** - * Create a new {@code Configuration} object from the specified {@code URI}. - * - * @param uri the {@code URI} - * @throws SecurityException if the {@code Configuration} can not be - * initialized - * @throws NullPointerException if {@code uri} is null - */ - public ConfigSpiFile(URI uri) { - // only load config from the specified URI - try { - url = uri.toURL(); - init(); - } catch (IOException ioe) { - throw new SecurityException(ioe); - } - } - - public ConfigSpiFile(final Configuration.Parameters params) - throws IOException { - - // call in a doPrivileged - // - // we have already passed the Configuration.getInstance - // security check. also this class is not freely accessible - // (it is in the "sun" package). - - try { - AccessController.doPrivileged(new PrivilegedExceptionAction() { - public Void run() throws IOException { - if (params == null) { - init(); - } else { - if (!(params instanceof URIParameter)) { - throw new IllegalArgumentException - ("Unrecognized parameter: " + params); - } - URIParameter uriParam = (URIParameter)params; - url = uriParam.getURI().toURL(); - init(); - } - return null; - } - }); - } catch (PrivilegedActionException pae) { - throw (IOException)pae.getException(); - } - - // if init() throws some other RuntimeException, - // let it percolate up naturally. - } - - /** - * Read and initialize the entire login Configuration from the configured - * URL. - * - * @throws IOException if the Configuration can not be initialized - * @throws SecurityException if the caller does not have permission - * to initialize the Configuration - */ - private void init() throws IOException { - - boolean initialized = false; - - // For policy.expandProperties, check if either a security or system - // property is set to false (old code erroneously checked the system - // prop so we must check both to preserve compatibility). - String expand = Security.getProperty("policy.expandProperties"); - if (expand == null) { - expand = System.getProperty("policy.expandProperties"); - } - if ("false".equals(expand)) { - expandProp = false; - } - - // new configuration - Map> newConfig = new HashMap<>(); - - if (url != null) { - /** - * If the caller specified a URI via Configuration.getInstance, - * we only read from that URI - */ - if (debugConfig != null) { - debugConfig.println("reading " + url); - } - init(url, newConfig); - configuration = newConfig; - return; - } - - /** - * Caller did not specify URI via Configuration.getInstance. - * Read from URLs listed in the java.security properties file. - */ - String allowSys = Security.getProperty("policy.allowSystemProperty"); - - if ("true".equalsIgnoreCase(allowSys)) { - String extra_config = System.getProperty - ("java.security.auth.login.config"); - if (extra_config != null) { - boolean overrideAll = false; - if (extra_config.startsWith("=")) { - overrideAll = true; - extra_config = extra_config.substring(1); - } - try { - extra_config = PropertyExpander.expand(extra_config); - } catch (PropertyExpander.ExpandException peee) { - MessageFormat form = new MessageFormat - (ResourcesMgr.getString - ("Unable.to.properly.expand.config", - "sun.security.util.AuthResources")); - Object[] source = {extra_config}; - throw new IOException(form.format(source)); - } - - URL configURL = null; - try { - configURL = new URL(extra_config); - } catch (MalformedURLException mue) { - File configFile = new File(extra_config); - if (configFile.exists()) { - configURL = configFile.toURI().toURL(); - } else { - MessageFormat form = new MessageFormat - (ResourcesMgr.getString - ("extra.config.No.such.file.or.directory.", - "sun.security.util.AuthResources")); - Object[] source = {extra_config}; - throw new IOException(form.format(source)); - } - } - - if (debugConfig != null) { - debugConfig.println("reading "+configURL); - } - init(configURL, newConfig); - initialized = true; - if (overrideAll) { - if (debugConfig != null) { - debugConfig.println("overriding other policies!"); - } - configuration = newConfig; - return; - } - } - } - - int n = 1; - String config_url; - while ((config_url = Security.getProperty - ("login.config.url."+n)) != null) { - try { - config_url = PropertyExpander.expand - (config_url).replace(File.separatorChar, '/'); - if (debugConfig != null) { - debugConfig.println("\tReading config: " + config_url); - } - init(new URL(config_url), newConfig); - initialized = true; - } catch (PropertyExpander.ExpandException peee) { - MessageFormat form = new MessageFormat - (ResourcesMgr.getString - ("Unable.to.properly.expand.config", - "sun.security.util.AuthResources")); - Object[] source = {config_url}; - throw new IOException(form.format(source)); - } - n++; - } - - if (initialized == false && n == 1 && config_url == null) { - - // get the config from the user's home directory - if (debugConfig != null) { - debugConfig.println("\tReading Policy " + - "from ~/.java.login.config"); - } - config_url = System.getProperty("user.home"); - String userConfigFile = config_url + - File.separatorChar + ".java.login.config"; - - // No longer throws an exception when there's no config file - // at all. Returns an empty Configuration instead. - if (new File(userConfigFile).exists()) { - init(new File(userConfigFile).toURI().toURL(), - newConfig); - } - } - - configuration = newConfig; - } - - private void init(URL config, - Map> newConfig) - throws IOException { - - try (InputStreamReader isr - = new InputStreamReader(getInputStream(config), "UTF-8")) { - readConfig(isr, newConfig); - } catch (FileNotFoundException fnfe) { - if (debugConfig != null) { - debugConfig.println(fnfe.toString()); - } - throw new IOException(ResourcesMgr.getString - ("Configuration.Error.No.such.file.or.directory", - "sun.security.util.AuthResources")); - } - } - - /** - * Retrieve an entry from the Configuration using an application name - * as an index. - * - * @param applicationName the name used to index the Configuration. - * @return an array of AppConfigurationEntries which correspond to - * the stacked configuration of LoginModules for this - * application, or null if this application has no configured - * LoginModules. - */ - @Override - public AppConfigurationEntry[] engineGetAppConfigurationEntry - (String applicationName) { - - List list = null; - synchronized (configuration) { - list = configuration.get(applicationName); - } - - if (list == null || list.size() == 0) - return null; - - AppConfigurationEntry[] entries = - new AppConfigurationEntry[list.size()]; - Iterator iterator = list.iterator(); - for (int i = 0; iterator.hasNext(); i++) { - AppConfigurationEntry e = iterator.next(); - entries[i] = new AppConfigurationEntry(e.getLoginModuleName(), - e.getControlFlag(), - e.getOptions()); - } - return entries; - } - - /** - * Refresh and reload the Configuration by re-reading all of the - * login configurations. - * - * @throws SecurityException if the caller does not have permission - * to refresh the Configuration. - */ - @Override - public synchronized void engineRefresh() { - - SecurityManager sm = System.getSecurityManager(); - if (sm != null) - sm.checkPermission(new AuthPermission("refreshLoginConfiguration")); - - AccessController.doPrivileged(new PrivilegedAction() { - public Void run() { - try { - init(); - } catch (IOException ioe) { - throw new SecurityException(ioe.getLocalizedMessage(), ioe); - } - return null; - } - }); - } - - private void readConfig(Reader reader, - Map> newConfig) - throws IOException { - - linenum = 1; - - if (!(reader instanceof BufferedReader)) - reader = new BufferedReader(reader); - - st = new StreamTokenizer(reader); - st.quoteChar('"'); - st.wordChars('$', '$'); - st.wordChars('_', '_'); - st.wordChars('-', '-'); - st.wordChars('*', '*'); - st.lowerCaseMode(false); - st.slashSlashComments(true); - st.slashStarComments(true); - st.eolIsSignificant(true); - - lookahead = nextToken(); - while (lookahead != StreamTokenizer.TT_EOF) { - parseLoginEntry(newConfig); - } - } - - private void parseLoginEntry( - Map> newConfig) - throws IOException { - - List configEntries = new LinkedList<>(); - - // application name - String appName = st.sval; - lookahead = nextToken(); - - if (debugParser != null) { - debugParser.println("\tReading next config entry: " + appName); - } - - match("{"); - - // get the modules - while (peek("}") == false) { - // get the module class name - String moduleClass = match("module class name"); - - // controlFlag (required, optional, etc) - AppConfigurationEntry.LoginModuleControlFlag controlFlag; - String sflag = match("controlFlag").toUpperCase(); - switch (sflag) { - case "REQUIRED": - controlFlag = - AppConfigurationEntry.LoginModuleControlFlag.REQUIRED; - break; - case "REQUISITE": - controlFlag = - AppConfigurationEntry.LoginModuleControlFlag.REQUISITE; - break; - case "SUFFICIENT": - controlFlag = - AppConfigurationEntry.LoginModuleControlFlag.SUFFICIENT; - break; - case "OPTIONAL": - controlFlag = - AppConfigurationEntry.LoginModuleControlFlag.OPTIONAL; - break; - default: - MessageFormat form = new MessageFormat( - ResourcesMgr.getString - ("Configuration.Error.Invalid.control.flag.flag", - "sun.security.util.AuthResources")); - Object[] source = {sflag}; - throw new IOException(form.format(source)); - } - - // get the args - Map options = new HashMap<>(); - while (peek(";") == false) { - String key = match("option key"); - match("="); - try { - options.put(key, expand(match("option value"))); - } catch (PropertyExpander.ExpandException peee) { - throw new IOException(peee.getLocalizedMessage()); - } - } - - lookahead = nextToken(); - - // create the new element - if (debugParser != null) { - debugParser.println("\t\t" + moduleClass + ", " + sflag); - for (String key : options.keySet()) { - debugParser.println("\t\t\t" + key + - "=" + options.get(key)); - } - } - configEntries.add(new AppConfigurationEntry(moduleClass, - controlFlag, options)); - } - - match("}"); - match(";"); - - // add this configuration entry - if (newConfig.containsKey(appName)) { - MessageFormat form = new MessageFormat(ResourcesMgr.getString - ("Configuration.Error.Can.not.specify.multiple.entries.for.appName", - "sun.security.util.AuthResources")); - Object[] source = {appName}; - throw new IOException(form.format(source)); - } - newConfig.put(appName, configEntries); - } - - private String match(String expect) throws IOException { - - String value = null; - - switch(lookahead) { - case StreamTokenizer.TT_EOF: - - MessageFormat form1 = new MessageFormat(ResourcesMgr.getString - ("Configuration.Error.expected.expect.read.end.of.file.", - "sun.security.util.AuthResources")); - Object[] source1 = {expect}; - throw new IOException(form1.format(source1)); - - case '"': - case StreamTokenizer.TT_WORD: - - if (expect.equalsIgnoreCase("module class name") || - expect.equalsIgnoreCase("controlFlag") || - expect.equalsIgnoreCase("option key") || - expect.equalsIgnoreCase("option value")) { - value = st.sval; - lookahead = nextToken(); - } else { - MessageFormat form = new MessageFormat(ResourcesMgr.getString - ("Configuration.Error.Line.line.expected.expect.found.value.", - "sun.security.util.AuthResources")); - Object[] source = {new Integer(linenum), expect, st.sval}; - throw new IOException(form.format(source)); - } - break; - - case '{': - - if (expect.equalsIgnoreCase("{")) { - lookahead = nextToken(); - } else { - MessageFormat form = new MessageFormat(ResourcesMgr.getString - ("Configuration.Error.Line.line.expected.expect.", - "sun.security.util.AuthResources")); - Object[] source = {new Integer(linenum), expect, st.sval}; - throw new IOException(form.format(source)); - } - break; - - case ';': - - if (expect.equalsIgnoreCase(";")) { - lookahead = nextToken(); - } else { - MessageFormat form = new MessageFormat(ResourcesMgr.getString - ("Configuration.Error.Line.line.expected.expect.", - "sun.security.util.AuthResources")); - Object[] source = {new Integer(linenum), expect, st.sval}; - throw new IOException(form.format(source)); - } - break; - - case '}': - - if (expect.equalsIgnoreCase("}")) { - lookahead = nextToken(); - } else { - MessageFormat form = new MessageFormat(ResourcesMgr.getString - ("Configuration.Error.Line.line.expected.expect.", - "sun.security.util.AuthResources")); - Object[] source = {new Integer(linenum), expect, st.sval}; - throw new IOException(form.format(source)); - } - break; - - case '=': - - if (expect.equalsIgnoreCase("=")) { - lookahead = nextToken(); - } else { - MessageFormat form = new MessageFormat(ResourcesMgr.getString - ("Configuration.Error.Line.line.expected.expect.", - "sun.security.util.AuthResources")); - Object[] source = {new Integer(linenum), expect, st.sval}; - throw new IOException(form.format(source)); - } - break; - - default: - MessageFormat form = new MessageFormat(ResourcesMgr.getString - ("Configuration.Error.Line.line.expected.expect.found.value.", - "sun.security.util.AuthResources")); - Object[] source = {new Integer(linenum), expect, st.sval}; - throw new IOException(form.format(source)); - } - return value; - } - - private boolean peek(String expect) { - boolean found = false; - - switch (lookahead) { - case ',': - if (expect.equalsIgnoreCase(",")) - found = true; - break; - case ';': - if (expect.equalsIgnoreCase(";")) - found = true; - break; - case '{': - if (expect.equalsIgnoreCase("{")) - found = true; - break; - case '}': - if (expect.equalsIgnoreCase("}")) - found = true; - break; - default: - } - return found; - } - - private int nextToken() throws IOException { - int tok; - while ((tok = st.nextToken()) == StreamTokenizer.TT_EOL) { - linenum++; - } - return tok; - } - - private InputStream getInputStream(URL url) throws IOException { - if ("file".equalsIgnoreCase(url.getProtocol())) { - // Compatibility notes: - // - // Code changed from - // String path = url.getFile().replace('/', File.separatorChar); - // return new FileInputStream(path); - // - // The original implementation would search for "/tmp/a%20b" - // when url is "file:///tmp/a%20b". This is incorrect. The - // current codes fix this bug and searches for "/tmp/a b". - // For compatibility reasons, when the file "/tmp/a b" does - // not exist, the file named "/tmp/a%20b" will be tried. - // - // This also means that if both file exists, the behavior of - // this method is changed, and the current codes choose the - // correct one. - try { - return url.openStream(); - } catch (Exception e) { - String file = url.getPath(); - if (url.getHost().length() > 0) { // For Windows UNC - file = "//" + url.getHost() + file; - } - if (debugConfig != null) { - debugConfig.println("cannot read " + url + - ", try " + file); - } - return new FileInputStream(file); - } - } else { - return url.openStream(); - } - } - - private String expand(String value) - throws PropertyExpander.ExpandException, IOException { - - if (value.isEmpty()) { - return value; - } - - if (expandProp) { - - String s = PropertyExpander.expand(value); - - if (s == null || s.length() == 0) { - MessageFormat form = new MessageFormat(ResourcesMgr.getString - ("Configuration.Error.Line.line.system.property.value.expanded.to.empty.value", - "sun.security.util.AuthResources")); - Object[] source = {new Integer(linenum), value}; - throw new IOException(form.format(source)); - } - return s; - } else { - return value; - } - } -}