984 lines · 31.4 KB · Java
RawDownload
/* * Copyright (c) 2003, 2011, 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.pkcs11; import java.io.*;import static java.io.StreamTokenizer.*;import java.math.BigInteger;import java.util.*; import java.security.*; import sun.security.action.GetPropertyAction;import sun.security.util.PropertyExpander; import sun.security.pkcs11.wrapper.*;import static sun.security.pkcs11.wrapper.PKCS11Constants.*;import static sun.security.pkcs11.wrapper.CK_ATTRIBUTE.*; import static sun.security.pkcs11.TemplateManager.*; /** * Configuration container and file parsing. * * @author  Andreas Sterbenz * @since   1.5 */final class Config {     static final int ERR_HALT       = 1;    static final int ERR_IGNORE_ALL = 2;    static final int ERR_IGNORE_LIB = 3;     // same as allowSingleThreadedModules but controlled via a system property    // and applied to all providers. if set to false, no SunPKCS11 instances    // will accept single threaded modules regardless of the setting in their    // config files.    private static final boolean staticAllowSingleThreadedModules;     static {        String p = "sun.security.pkcs11.allowSingleThreadedModules";        String s = AccessController.doPrivileged(new GetPropertyAction(p));        if ("false".equalsIgnoreCase(s)) {            staticAllowSingleThreadedModules = false;        } else {            staticAllowSingleThreadedModules = true;        }    }     // temporary storage for configurations    // needed because the SunPKCS11 needs to call the superclass constructor    // in provider before accessing any instance variables    private final static Map<String,Config> configMap =                                        new HashMap<String,Config>();     static Config getConfig(final String name, final InputStream stream) {        Config config = configMap.get(name);        if (config != null) {            return config;        }        try {            config = new Config(name, stream);            configMap.put(name, config);            return config;        } catch (Exception e) {            throw new ProviderException("Error parsing configuration", e);        }    }     static Config removeConfig(String name) {        return configMap.remove(name);    }     private final static boolean DEBUG = false;     private static void debug(Object o) {        if (DEBUG) {            System.out.println(o);        }    }     // Reader and StringTokenizer used during parsing    private Reader reader;     private StreamTokenizer st;     private Set<String> parsedKeywords;     // name suffix of the provider    private String name;     // name of the PKCS#11 library    private String library;     // description to pass to the provider class    private String description;     // slotID of the slot to use    private int slotID = -1;     // slot to use, specified as index in the slotlist    private int slotListIndex = -1;     // set of enabled mechanisms (or null to use default)    private Set<Long> enabledMechanisms;     // set of disabled mechanisms    private Set<Long> disabledMechanisms;     // whether to print debug info during startup    private boolean showInfo = false;     // template manager, initialized from parsed attributes    private TemplateManager templateManager;     // how to handle error during startup, one of ERR_    private int handleStartupErrors = ERR_HALT;     // flag indicating whether the P11KeyStore should    // be more tolerant of input parameters    private boolean keyStoreCompatibilityMode = true;     // flag indicating whether we need to explicitly cancel operations    // see Token    private boolean explicitCancel = true;     // how often to test for token insertion, if no token is present    private int insertionCheckInterval = 2000;     // flag inidicating whether to omit the call to C_Initialize()    // should be used only if we are running within a process that    // has already called it (e.g. Plugin inside of Mozilla/NSS)    private boolean omitInitialize = false;     // whether to allow modules that only support single threaded access.    // they cannot be used safely from multiple PKCS#11 consumers in the    // same process, for example NSS and SunPKCS11    private boolean allowSingleThreadedModules = true;     // name of the C function that returns the PKCS#11 functionlist    // This option primarily exists for the deprecated    // Secmod.Module.getProvider() method.    private String functionList = "C_GetFunctionList";     // whether to use NSS secmod mode. Implicitly set if nssLibraryDirectory,    // nssSecmodDirectory, or nssModule is specified.    private boolean nssUseSecmod;     // location of the NSS library files (libnss3.so, etc.)    private String nssLibraryDirectory;     // location of secmod.db    private String nssSecmodDirectory;     // which NSS module to use    private String nssModule;     private Secmod.DbMode nssDbMode = Secmod.DbMode.READ_WRITE;     // Whether the P11KeyStore should specify the CKA_NETSCAPE_DB attribute    // when creating private keys. Only valid if nssUseSecmod is true.    private boolean nssNetscapeDbWorkaround = true;     // Special init argument string for the NSS softtoken.    // This is used when using the NSS softtoken directly without secmod mode.    private String nssArgs;     // whether to use NSS trust attributes for the KeyStore of this provider    // this option is for internal use by the SunPKCS11 code only and    // works only for NSS providers created via the Secmod API    private boolean nssUseSecmodTrust = false;     private Config(String filename, InputStream in) throws IOException {        if (in == null) {            if (filename.startsWith("--")) {                // inline config                String config = filename.substring(2).replace("\\n", "\n");                reader = new StringReader(config);            } else {                in = new FileInputStream(expand(filename));            }        }        if (reader == null) {            reader = new BufferedReader(new InputStreamReader(in));        }        parsedKeywords = new HashSet<String>();        st = new StreamTokenizer(reader);        setupTokenizer();        parse();    }     String getName() {        return name;    }     String getLibrary() {        return library;    }     String getDescription() {        if (description != null) {            return description;        }        return "SunPKCS11-" + name + " using library " + library;    }     int getSlotID() {        return slotID;    }     int getSlotListIndex() {        if ((slotID == -1) && (slotListIndex == -1)) {            // if neither is set, default to first slot            return 0;        } else {            return slotListIndex;        }    }     boolean getShowInfo() {        return (SunPKCS11.debug != null) || showInfo;    }     TemplateManager getTemplateManager() {        if (templateManager == null) {            templateManager = new TemplateManager();        }        return templateManager;    }     boolean isEnabled(long m) {        if (enabledMechanisms != null) {            return enabledMechanisms.contains(Long.valueOf(m));        }        if (disabledMechanisms != null) {            return !disabledMechanisms.contains(Long.valueOf(m));        }        return true;    }     int getHandleStartupErrors() {        return handleStartupErrors;    }     boolean getKeyStoreCompatibilityMode() {        return keyStoreCompatibilityMode;    }     boolean getExplicitCancel() {        return explicitCancel;    }     int getInsertionCheckInterval() {        return insertionCheckInterval;    }     boolean getOmitInitialize() {        return omitInitialize;    }     boolean getAllowSingleThreadedModules() {        return staticAllowSingleThreadedModules && allowSingleThreadedModules;    }     String getFunctionList() {        return functionList;    }     boolean getNssUseSecmod() {        return nssUseSecmod;    }     String getNssLibraryDirectory() {        return nssLibraryDirectory;    }     String getNssSecmodDirectory() {        return nssSecmodDirectory;    }     String getNssModule() {        return nssModule;    }     Secmod.DbMode getNssDbMode() {        return nssDbMode;    }     public boolean getNssNetscapeDbWorkaround() {        return nssUseSecmod && nssNetscapeDbWorkaround;    }     String getNssArgs() {        return nssArgs;    }     boolean getNssUseSecmodTrust() {        return nssUseSecmodTrust;    }     private static String expand(final String s) throws IOException {        try {            return PropertyExpander.expand(s);        } catch (Exception e) {            throw new RuntimeException(e.getMessage());        }    }     private void setupTokenizer() {        st.resetSyntax();        st.wordChars('a', 'z');        st.wordChars('A', 'Z');        st.wordChars('0', '9');        st.wordChars(':', ':');        st.wordChars('.', '.');        st.wordChars('_', '_');        st.wordChars('-', '-');        st.wordChars('/', '/');        st.wordChars('\\', '\\');        st.wordChars('$', '$');        st.wordChars('{', '{'); // need {} for property subst        st.wordChars('}', '}');        st.wordChars('*', '*');        st.wordChars('+', '+');        st.wordChars('~', '~');        // XXX check ASCII table and add all other characters except special         // special: #="(),        st.whitespaceChars(0, ' ');        st.commentChar('#');        st.eolIsSignificant(true);        st.quoteChar('\"');    }     private ConfigurationException excToken(String msg) {        return new ConfigurationException(msg + " " + st);    }     private ConfigurationException excLine(String msg) {        return new ConfigurationException(msg + ", line " + st.lineno());    }     private void parse() throws IOException {        while (true) {            int token = nextToken();            if (token == TT_EOF) {                break;            }            if (token == TT_EOL) {                continue;            }            if (token != TT_WORD) {                throw excToken("Unexpected token:");            }            String word = st.sval;            if (word.equals("name")) {                name = parseStringEntry(word);            } else if (word.equals("library")) {                library = parseLibrary(word);            } else if (word.equals("description")) {                parseDescription(word);            } else if (word.equals("slot")) {                parseSlotID(word);            } else if (word.equals("slotListIndex")) {                parseSlotListIndex(word);            } else if (word.equals("enabledMechanisms")) {                parseEnabledMechanisms(word);            } else if (word.equals("disabledMechanisms")) {                parseDisabledMechanisms(word);            } else if (word.equals("attributes")) {                parseAttributes(word);            } else if (word.equals("handleStartupErrors")) {                parseHandleStartupErrors(word);            } else if (word.endsWith("insertionCheckInterval")) {                insertionCheckInterval = parseIntegerEntry(word);                if (insertionCheckInterval < 100) {                    throw excLine(word + " must be at least 100 ms");                }            } else if (word.equals("showInfo")) {                showInfo = parseBooleanEntry(word);            } else if (word.equals("keyStoreCompatibilityMode")) {                keyStoreCompatibilityMode = parseBooleanEntry(word);            } else if (word.equals("explicitCancel")) {                explicitCancel = parseBooleanEntry(word);            } else if (word.equals("omitInitialize")) {                omitInitialize = parseBooleanEntry(word);            } else if (word.equals("allowSingleThreadedModules")) {                allowSingleThreadedModules = parseBooleanEntry(word);            } else if (word.equals("functionList")) {                functionList = parseStringEntry(word);            } else if (word.equals("nssUseSecmod")) {                nssUseSecmod = parseBooleanEntry(word);            } else if (word.equals("nssLibraryDirectory")) {                nssLibraryDirectory = parseLibrary(word);                nssUseSecmod = true;            } else if (word.equals("nssSecmodDirectory")) {                nssSecmodDirectory = expand(parseStringEntry(word));                nssUseSecmod = true;            } else if (word.equals("nssModule")) {                nssModule = parseStringEntry(word);                nssUseSecmod = true;            } else if (word.equals("nssDbMode")) {                String mode = parseStringEntry(word);                if (mode.equals("readWrite")) {                    nssDbMode = Secmod.DbMode.READ_WRITE;                } else if (mode.equals("readOnly")) {                    nssDbMode = Secmod.DbMode.READ_ONLY;                } else if (mode.equals("noDb")) {                    nssDbMode = Secmod.DbMode.NO_DB;                } else {                    throw excToken("nssDbMode must be one of readWrite, readOnly, and noDb:");                }                nssUseSecmod = true;            } else if (word.equals("nssNetscapeDbWorkaround")) {                nssNetscapeDbWorkaround = parseBooleanEntry(word);                nssUseSecmod = true;            } else if (word.equals("nssArgs")) {                parseNSSArgs(word);            } else if (word.equals("nssUseSecmodTrust")) {                nssUseSecmodTrust = parseBooleanEntry(word);            } else {                throw new ConfigurationException                        ("Unknown keyword '" + word + "', line " + st.lineno());            }            parsedKeywords.add(word);        }        reader.close();        reader = null;        st = null;        parsedKeywords = null;        if (name == null) {            throw new ConfigurationException("name must be specified");        }        if (nssUseSecmod == false) {            if (library == null) {                throw new ConfigurationException("library must be specified");            }        } else {            if (library != null) {                throw new ConfigurationException                    ("library must not be specified in NSS mode");            }            if ((slotID != -1) || (slotListIndex != -1)) {                throw new ConfigurationException                    ("slot and slotListIndex must not be specified in NSS mode");            }            if (nssArgs != null) {                throw new ConfigurationException                    ("nssArgs must not be specified in NSS mode");            }            if (nssUseSecmodTrust != false) {                throw new ConfigurationException("nssUseSecmodTrust is an "                    + "internal option and must not be specified in NSS mode");            }        }    }     //    // Parsing helper methods    //     private int nextToken() throws IOException {        int token = st.nextToken();        debug(st);        return token;    }     private void parseEquals() throws IOException {        int token = nextToken();        if (token != '=') {            throw excToken("Expected '=', read");        }    }     private void parseOpenBraces() throws IOException {        while (true) {            int token = nextToken();            if (token == TT_EOL) {

Lines 1–500 of 984.