History

My first initial commit with all of mine experimental changes.

Dmitry Kabak (userdima committed 13 years ago

Commit d37b88d1 parent 3f5b46618352 files · +2598093 −-8690Browse files

Showing the changes to java/pkg/sun/security/pkcs11/Config.java (1 of 18352 files). Show all

Unified · Split

java/pkg/sun/security/pkcs11/Config.java+984−0
@@ -0,0 +1,984 @@
1+/*
2+ * Copyright (c) 2003, 2011, 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 sun.security.pkcs11;
27+
28+import java.io.*;
29+import static java.io.StreamTokenizer.*;
30+import java.math.BigInteger;
31+import java.util.*;
32+
33+import java.security.*;
34+
35+import sun.security.action.GetPropertyAction;
36+import sun.security.util.PropertyExpander;
37+
38+import sun.security.pkcs11.wrapper.*;
39+import static sun.security.pkcs11.wrapper.PKCS11Constants.*;
40+import static sun.security.pkcs11.wrapper.CK_ATTRIBUTE.*;
41+
42+import static sun.security.pkcs11.TemplateManager.*;
43+
44+/**
45+ * Configuration container and file parsing.
46+ *
47+ * @author Andreas Sterbenz
48+ * @since 1.5
49+ */
50+final class Config {
51+
52+ static final int ERR_HALT = 1;
53+ static final int ERR_IGNORE_ALL = 2;
54+ static final int ERR_IGNORE_LIB = 3;
55+
56+ // same as allowSingleThreadedModules but controlled via a system property
57+ // and applied to all providers. if set to false, no SunPKCS11 instances
58+ // will accept single threaded modules regardless of the setting in their
59+ // config files.
60+ private static final boolean staticAllowSingleThreadedModules;
61+
62+ static {
63+ String p = "sun.security.pkcs11.allowSingleThreadedModules";
64+ String s = AccessController.doPrivileged(new GetPropertyAction(p));
65+ if ("false".equalsIgnoreCase(s)) {
66+ staticAllowSingleThreadedModules = false;
67+ } else {
68+ staticAllowSingleThreadedModules = true;
69+ }
70+ }
71+
72+ // temporary storage for configurations
73+ // needed because the SunPKCS11 needs to call the superclass constructor
74+ // in provider before accessing any instance variables
75+ private final static Map<String,Config> configMap =
76+ new HashMap<String,Config>();
77+
78+ static Config getConfig(final String name, final InputStream stream) {
79+ Config config = configMap.get(name);
80+ if (config != null) {
81+ return config;
82+ }
83+ try {
84+ config = new Config(name, stream);
85+ configMap.put(name, config);
86+ return config;
87+ } catch (Exception e) {
88+ throw new ProviderException("Error parsing configuration", e);
89+ }
90+ }
91+
92+ static Config removeConfig(String name) {
93+ return configMap.remove(name);
94+ }
95+
96+ private final static boolean DEBUG = false;
97+
98+ private static void debug(Object o) {
99+ if (DEBUG) {
100+ System.out.println(o);
101+ }
102+ }
103+
104+ // Reader and StringTokenizer used during parsing
105+ private Reader reader;
106+
107+ private StreamTokenizer st;
108+
109+ private Set<String> parsedKeywords;
110+
111+ // name suffix of the provider
112+ private String name;
113+
114+ // name of the PKCS#11 library
115+ private String library;
116+
117+ // description to pass to the provider class
118+ private String description;
119+
120+ // slotID of the slot to use
121+ private int slotID = -1;
122+
123+ // slot to use, specified as index in the slotlist
124+ private int slotListIndex = -1;
125+
126+ // set of enabled mechanisms (or null to use default)
127+ private Set<Long> enabledMechanisms;
128+
129+ // set of disabled mechanisms
130+ private Set<Long> disabledMechanisms;
131+
132+ // whether to print debug info during startup
133+ private boolean showInfo = false;
134+
135+ // template manager, initialized from parsed attributes
136+ private TemplateManager templateManager;
137+
138+ // how to handle error during startup, one of ERR_
139+ private int handleStartupErrors = ERR_HALT;
140+
141+ // flag indicating whether the P11KeyStore should
142+ // be more tolerant of input parameters
143+ private boolean keyStoreCompatibilityMode = true;
144+
145+ // flag indicating whether we need to explicitly cancel operations
146+ // see Token
147+ private boolean explicitCancel = true;
148+
149+ // how often to test for token insertion, if no token is present
150+ private int insertionCheckInterval = 2000;
151+
152+ // flag inidicating whether to omit the call to C_Initialize()
153+ // should be used only if we are running within a process that
154+ // has already called it (e.g. Plugin inside of Mozilla/NSS)
155+ private boolean omitInitialize = false;
156+
157+ // whether to allow modules that only support single threaded access.
158+ // they cannot be used safely from multiple PKCS#11 consumers in the
159+ // same process, for example NSS and SunPKCS11
160+ private boolean allowSingleThreadedModules = true;
161+
162+ // name of the C function that returns the PKCS#11 functionlist
163+ // This option primarily exists for the deprecated
164+ // Secmod.Module.getProvider() method.
165+ private String functionList = "C_GetFunctionList";
166+
167+ // whether to use NSS secmod mode. Implicitly set if nssLibraryDirectory,
168+ // nssSecmodDirectory, or nssModule is specified.
169+ private boolean nssUseSecmod;
170+
171+ // location of the NSS library files (libnss3.so, etc.)
172+ private String nssLibraryDirectory;
173+
174+ // location of secmod.db
175+ private String nssSecmodDirectory;
176+
177+ // which NSS module to use
178+ private String nssModule;
179+
180+ private Secmod.DbMode nssDbMode = Secmod.DbMode.READ_WRITE;
181+
182+ // Whether the P11KeyStore should specify the CKA_NETSCAPE_DB attribute
183+ // when creating private keys. Only valid if nssUseSecmod is true.
184+ private boolean nssNetscapeDbWorkaround = true;
185+
186+ // Special init argument string for the NSS softtoken.
187+ // This is used when using the NSS softtoken directly without secmod mode.
188+ private String nssArgs;
189+
190+ // whether to use NSS trust attributes for the KeyStore of this provider
191+ // this option is for internal use by the SunPKCS11 code only and
192+ // works only for NSS providers created via the Secmod API
193+ private boolean nssUseSecmodTrust = false;
194+
195+ private Config(String filename, InputStream in) throws IOException {
196+ if (in == null) {
197+ if (filename.startsWith("--")) {
198+ // inline config
199+ String config = filename.substring(2).replace("\\n", "\n");
200+ reader = new StringReader(config);
201+ } else {
202+ in = new FileInputStream(expand(filename));
203+ }
204+ }
205+ if (reader == null) {
206+ reader = new BufferedReader(new InputStreamReader(in));
207+ }
208+ parsedKeywords = new HashSet<String>();
209+ st = new StreamTokenizer(reader);
210+ setupTokenizer();
211+ parse();
212+ }
213+
214+ String getName() {
215+ return name;
216+ }
217+
218+ String getLibrary() {
219+ return library;
220+ }
221+
222+ String getDescription() {
223+ if (description != null) {
224+ return description;
225+ }
226+ return "SunPKCS11-" + name + " using library " + library;
227+ }
228+
229+ int getSlotID() {
230+ return slotID;
231+ }
232+
233+ int getSlotListIndex() {
234+ if ((slotID == -1) && (slotListIndex == -1)) {
235+ // if neither is set, default to first slot
236+ return 0;
237+ } else {
238+ return slotListIndex;
239+ }
240+ }
241+
242+ boolean getShowInfo() {
243+ return (SunPKCS11.debug != null) || showInfo;
244+ }
245+
246+ TemplateManager getTemplateManager() {
247+ if (templateManager == null) {
248+ templateManager = new TemplateManager();
249+ }
250+ return templateManager;
251+ }
252+
253+ boolean isEnabled(long m) {
254+ if (enabledMechanisms != null) {
255+ return enabledMechanisms.contains(Long.valueOf(m));
256+ }
257+ if (disabledMechanisms != null) {
258+ return !disabledMechanisms.contains(Long.valueOf(m));
259+ }
260+ return true;
261+ }
262+
263+ int getHandleStartupErrors() {
264+ return handleStartupErrors;
265+ }
266+
267+ boolean getKeyStoreCompatibilityMode() {
268+ return keyStoreCompatibilityMode;
269+ }
270+
271+ boolean getExplicitCancel() {
272+ return explicitCancel;
273+ }
274+
275+ int getInsertionCheckInterval() {
276+ return insertionCheckInterval;
277+ }
278+
279+ boolean getOmitInitialize() {
280+ return omitInitialize;
281+ }
282+
283+ boolean getAllowSingleThreadedModules() {
284+ return staticAllowSingleThreadedModules && allowSingleThreadedModules;
285+ }
286+
287+ String getFunctionList() {
288+ return functionList;
289+ }
290+
291+ boolean getNssUseSecmod() {
292+ return nssUseSecmod;
293+ }
294+
295+ String getNssLibraryDirectory() {
296+ return nssLibraryDirectory;
297+ }
298+
299+ String getNssSecmodDirectory() {
300+ return nssSecmodDirectory;
301+ }
302+
303+ String getNssModule() {
304+ return nssModule;
305+ }
306+
307+ Secmod.DbMode getNssDbMode() {
308+ return nssDbMode;
309+ }
310+
311+ public boolean getNssNetscapeDbWorkaround() {
312+ return nssUseSecmod && nssNetscapeDbWorkaround;
313+ }
314+
315+ String getNssArgs() {
316+ return nssArgs;
317+ }
318+
319+ boolean getNssUseSecmodTrust() {
320+ return nssUseSecmodTrust;
321+ }
322+
323+ private static String expand(final String s) throws IOException {
324+ try {
325+ return PropertyExpander.expand(s);
326+ } catch (Exception e) {
327+ throw new RuntimeException(e.getMessage());
328+ }
329+ }
330+
331+ private void setupTokenizer() {
332+ st.resetSyntax();
333+ st.wordChars('a', 'z');
334+ st.wordChars('A', 'Z');
335+ st.wordChars('0', '9');
336+ st.wordChars(':', ':');
337+ st.wordChars('.', '.');
338+ st.wordChars('_', '_');
339+ st.wordChars('-', '-');
340+ st.wordChars('/', '/');
341+ st.wordChars('\\', '\\');
342+ st.wordChars('$', '$');
343+ st.wordChars('{', '{'); // need {} for property subst
344+ st.wordChars('}', '}');
345+ st.wordChars('*', '*');
346+ st.wordChars('+', '+');
347+ st.wordChars('~', '~');
348+ // XXX check ASCII table and add all other characters except special
349+
350+ // special: #="(),
351+ st.whitespaceChars(0, ' ');
352+ st.commentChar('#');
353+ st.eolIsSignificant(true);
354+ st.quoteChar('\"');
355+ }
356+
357+ private ConfigurationException excToken(String msg) {
358+ return new ConfigurationException(msg + " " + st);
359+ }
360+
361+ private ConfigurationException excLine(String msg) {
362+ return new ConfigurationException(msg + ", line " + st.lineno());
363+ }
364+
365+ private void parse() throws IOException {
366+ while (true) {
367+ int token = nextToken();
368+ if (token == TT_EOF) {
369+ break;
370+ }
371+ if (token == TT_EOL) {
372+ continue;
373+ }
374+ if (token != TT_WORD) {
375+ throw excToken("Unexpected token:");
376+ }
377+ String word = st.sval;
378+ if (word.equals("name")) {
379+ name = parseStringEntry(word);
380+ } else if (word.equals("library")) {
381+ library = parseLibrary(word);
382+ } else if (word.equals("description")) {
383+ parseDescription(word);
384+ } else if (word.equals("slot")) {
385+ parseSlotID(word);
386+ } else if (word.equals("slotListIndex")) {
387+ parseSlotListIndex(word);
388+ } else if (word.equals("enabledMechanisms")) {
389+ parseEnabledMechanisms(word);
390+ } else if (word.equals("disabledMechanisms")) {
391+ parseDisabledMechanisms(word);
392+ } else if (word.equals("attributes")) {
393+ parseAttributes(word);
394+ } else if (word.equals("handleStartupErrors")) {
395+ parseHandleStartupErrors(word);
396+ } else if (word.endsWith("insertionCheckInterval")) {
397+ insertionCheckInterval = parseIntegerEntry(word);
398+ if (insertionCheckInterval < 100) {
399+ throw excLine(word + " must be at least 100 ms");
400+ }
401+ } else if (word.equals("showInfo")) {
402+ showInfo = parseBooleanEntry(word);
403+ } else if (word.equals("keyStoreCompatibilityMode")) {
404+ keyStoreCompatibilityMode = parseBooleanEntry(word);
405+ } else if (word.equals("explicitCancel")) {
406+ explicitCancel = parseBooleanEntry(word);
407+ } else if (word.equals("omitInitialize")) {
408+ omitInitialize = parseBooleanEntry(word);
409+ } else if (word.equals("allowSingleThreadedModules")) {
410+ allowSingleThreadedModules = parseBooleanEntry(word);
411+ } else if (word.equals("functionList")) {
412+ functionList = parseStringEntry(word);
413+ } else if (word.equals("nssUseSecmod")) {
414+ nssUseSecmod = parseBooleanEntry(word);
415+ } else if (word.equals("nssLibraryDirectory")) {
416+ nssLibraryDirectory = parseLibrary(word);
417+ nssUseSecmod = true;
418+ } else if (word.equals("nssSecmodDirectory")) {
419+ nssSecmodDirectory = expand(parseStringEntry(word));
420+ nssUseSecmod = true;
421+ } else if (word.equals("nssModule")) {
422+ nssModule = parseStringEntry(word);
423+ nssUseSecmod = true;
424+ } else if (word.equals("nssDbMode")) {
425+ String mode = parseStringEntry(word);
426+ if (mode.equals("readWrite")) {
427+ nssDbMode = Secmod.DbMode.READ_WRITE;
428+ } else if (mode.equals("readOnly")) {
429+ nssDbMode = Secmod.DbMode.READ_ONLY;
430+ } else if (mode.equals("noDb")) {
431+ nssDbMode = Secmod.DbMode.NO_DB;
432+ } else {
433+ throw excToken("nssDbMode must be one of readWrite, readOnly, and noDb:");
434+ }
435+ nssUseSecmod = true;
436+ } else if (word.equals("nssNetscapeDbWorkaround")) {
437+ nssNetscapeDbWorkaround = parseBooleanEntry(word);
438+ nssUseSecmod = true;
439+ } else if (word.equals("nssArgs")) {
440+ parseNSSArgs(word);
441+ } else if (word.equals("nssUseSecmodTrust")) {
442+ nssUseSecmodTrust = parseBooleanEntry(word);
443+ } else {
444+ throw new ConfigurationException
445+ ("Unknown keyword '" + word + "', line " + st.lineno());
446+ }
447+ parsedKeywords.add(word);
448+ }
449+ reader.close();
450+ reader = null;
451+ st = null;
452+ parsedKeywords = null;
453+ if (name == null) {
454+ throw new ConfigurationException("name must be specified");
455+ }
456+ if (nssUseSecmod == false) {
457+ if (library == null) {
458+ throw new ConfigurationException("library must be specified");
459+ }
460+ } else {
461+ if (library != null) {
462+ throw new ConfigurationException
463+ ("library must not be specified in NSS mode");
464+ }
465+ if ((slotID != -1) || (slotListIndex != -1)) {
466+ throw new ConfigurationException
467+ ("slot and slotListIndex must not be specified in NSS mode");
468+ }
469+ if (nssArgs != null) {
470+ throw new ConfigurationException
471+ ("nssArgs must not be specified in NSS mode");
472+ }
473+ if (nssUseSecmodTrust != false) {
474+ throw new ConfigurationException("nssUseSecmodTrust is an "
475+ + "internal option and must not be specified in NSS mode");
476+ }
477+ }
478+ }
479+
480+ //
481+ // Parsing helper methods
482+ //
483+
484+ private int nextToken() throws IOException {
485+ int token = st.nextToken();
486+ debug(st);
487+ return token;
488+ }
489+
490+ private void parseEquals() throws IOException {
491+ int token = nextToken();
492+ if (token != '=') {
493+ throw excToken("Expected '=', read");
494+ }
495+ }
496+
497+ private void parseOpenBraces() throws IOException {
498+ while (true) {
499+ int token = nextToken();
500+ if (token == TT_EOL) {
501+ continue;
502+ }
503+ if ((token == TT_WORD) && st.sval.equals("{")) {
504+ return;
505+ }
506+ throw excToken("Expected '{', read");
507+ }
508+ }
509+
510+ private boolean isCloseBraces(int token) {
511+ return (token == TT_WORD) && st.sval.equals("}");
512+ }
513+
514+ private String parseWord() throws IOException {
515+ int token = nextToken();
516+ if (token != TT_WORD) {
517+ throw excToken("Unexpected value:");
518+ }
519+ return st.sval;
520+ }
521+
522+ private String parseStringEntry(String keyword) throws IOException {
523+ checkDup(keyword);
524+ parseEquals();
525+
526+ int token = nextToken();
527+ if (token != TT_WORD && token != '\"') {
528+ // not a word token nor a string enclosed by double quotes
529+ throw excToken("Unexpected value:");
530+ }
531+ String value = st.sval;
532+
533+ debug(keyword + ": " + value);
534+ return value;
535+ }
536+
537+ private boolean parseBooleanEntry(String keyword) throws IOException {
538+ checkDup(keyword);
539+ parseEquals();
540+ boolean value = parseBoolean();
541+ debug(keyword + ": " + value);
542+ return value;
543+ }
544+
545+ private int parseIntegerEntry(String keyword) throws IOException {
546+ checkDup(keyword);
547+ parseEquals();
548+ int value = decodeNumber(parseWord());
549+ debug(keyword + ": " + value);
550+ return value;
551+ }
552+
553+ private boolean parseBoolean() throws IOException {
554+ String val = parseWord();
555+ if (val.equals("true")) {
556+ return true;
557+ } else if (val.equals("false")) {
558+ return false;
559+ } else {
560+ throw excToken("Expected boolean value, read:");
561+ }
562+ }
563+
564+ private String parseLine() throws IOException {
565+ String s = parseWord();
566+ while (true) {
567+ int token = nextToken();
568+ if ((token == TT_EOL) || (token == TT_EOF)) {
569+ break;
570+ }
571+ if (token != TT_WORD) {
572+ throw excToken("Unexpected value");
573+ }
574+ s = s + " " + st.sval;
575+ }
576+ return s;
577+ }
578+
579+ private int decodeNumber(String str) throws IOException {
580+ try {
581+ if (str.startsWith("0x") || str.startsWith("0X")) {
582+ return Integer.parseInt(str.substring(2), 16);
583+ } else {
584+ return Integer.parseInt(str);
585+ }
586+ } catch (NumberFormatException e) {
587+ throw excToken("Expected number, read");
588+ }
589+ }
590+
591+ private static boolean isNumber(String s) {
592+ if (s.length() == 0) {
593+ return false;
594+ }
595+ char ch = s.charAt(0);
596+ return ((ch >= '0') && (ch <= '9'));
597+ }
598+
599+ private void parseComma() throws IOException {
600+ int token = nextToken();
601+ if (token != ',') {
602+ throw excToken("Expected ',', read");
603+ }
604+ }
605+
606+ private static boolean isByteArray(String val) {
607+ return val.startsWith("0h");
608+ }
609+
610+ private byte[] decodeByteArray(String str) throws IOException {
611+ if (str.startsWith("0h") == false) {
612+ throw excToken("Expected byte array value, read");
613+ }
614+ str = str.substring(2);
615+ // XXX proper hex parsing
616+ try {
617+ return new BigInteger(str, 16).toByteArray();
618+ } catch (NumberFormatException e) {
619+ throw excToken("Expected byte array value, read");
620+ }
621+ }
622+
623+ private void checkDup(String keyword) throws IOException {
624+ if (parsedKeywords.contains(keyword)) {
625+ throw excLine(keyword + " must only be specified once");
626+ }
627+ }
628+
629+ //
630+ // individual entry parsing methods
631+ //
632+
633+ private String parseLibrary(String keyword) throws IOException {
634+ checkDup(keyword);
635+ parseEquals();
636+ String lib = parseLine();
637+ lib = expand(lib);
638+ int i = lib.indexOf("/$ISA/");
639+ if (i != -1) {
640+ // replace "/$ISA/" with "/sparcv9/" on 64-bit Solaris SPARC
641+ // and with "/amd64/" on Solaris AMD64.
642+ // On all other platforms, just turn it into a "/"
643+ String osName = System.getProperty("os.name", "");
644+ String osArch = System.getProperty("os.arch", "");
645+ String prefix = lib.substring(0, i);
646+ String suffix = lib.substring(i + 5);
647+ if (osName.equals("SunOS") && osArch.equals("sparcv9")) {
648+ lib = prefix + "/sparcv9" + suffix;
649+ } else if (osName.equals("SunOS") && osArch.equals("amd64")) {
650+ lib = prefix + "/amd64" + suffix;
651+ } else {
652+ lib = prefix + suffix;
653+ }
654+ }
655+ debug(keyword + ": " + lib);
656+
657+ // Check to see if full path is specified to prevent the DLL
658+ // preloading attack
659+ if (!(new File(lib)).isAbsolute()) {
660+ throw new ConfigurationException(
661+ "Absolute path required for library value: " + lib);
662+ }
663+ return lib;
664+ }
665+
666+ private void parseDescription(String keyword) throws IOException {
667+ checkDup(keyword);
668+ parseEquals();
669+ description = parseLine();
670+ debug("description: " + description);
671+ }
672+
673+ private void parseSlotID(String keyword) throws IOException {
674+ if (slotID >= 0) {
675+ throw excLine("Duplicate slot definition");
676+ }
677+ if (slotListIndex >= 0) {
678+ throw excLine
679+ ("Only one of slot and slotListIndex must be specified");
680+ }
681+ parseEquals();
682+ String slotString = parseWord();
683+ slotID = decodeNumber(slotString);
684+ debug("slot: " + slotID);
685+ }
686+
687+ private void parseSlotListIndex(String keyword) throws IOException {
688+ if (slotListIndex >= 0) {
689+ throw excLine("Duplicate slotListIndex definition");
690+ }
691+ if (slotID >= 0) {
692+ throw excLine
693+ ("Only one of slot and slotListIndex must be specified");
694+ }
695+ parseEquals();
696+ String slotString = parseWord();
697+ slotListIndex = decodeNumber(slotString);
698+ debug("slotListIndex: " + slotListIndex);
699+ }
700+
701+ private void parseEnabledMechanisms(String keyword) throws IOException {
702+ enabledMechanisms = parseMechanisms(keyword);
703+ }
704+
705+ private void parseDisabledMechanisms(String keyword) throws IOException {
706+ disabledMechanisms = parseMechanisms(keyword);
707+ }
708+
709+ private Set<Long> parseMechanisms(String keyword) throws IOException {
710+ checkDup(keyword);
711+ Set<Long> mechs = new HashSet<Long>();
712+ parseEquals();
713+ parseOpenBraces();
714+ while (true) {
715+ int token = nextToken();
716+ if (isCloseBraces(token)) {
717+ break;
718+ }
719+ if (token == TT_EOL) {
720+ continue;
721+ }
722+ if (token != TT_WORD) {
723+ throw excToken("Expected mechanism, read");
724+ }
725+ long mech = parseMechanism(st.sval);
726+ mechs.add(Long.valueOf(mech));
727+ }
728+ if (DEBUG) {
729+ System.out.print("mechanisms: [");
730+ for (Long mech : mechs) {
731+ System.out.print(Functions.getMechanismName(mech));
732+ System.out.print(", ");
733+ }
734+ System.out.println("]");
735+ }
736+ return mechs;
737+ }
738+
739+ private long parseMechanism(String mech) throws IOException {
740+ if (isNumber(mech)) {
741+ return decodeNumber(mech);
742+ } else {
743+ try {
744+ return Functions.getMechanismId(mech);
745+ } catch (IllegalArgumentException e) {
746+ throw excLine("Unknown mechanism: " + mech);
747+ }
748+ }
749+ }
750+
751+ private void parseAttributes(String keyword) throws IOException {
752+ if (templateManager == null) {
753+ templateManager = new TemplateManager();
754+ }
755+ int token = nextToken();
756+ if (token == '=') {
757+ String s = parseWord();
758+ if (s.equals("compatibility") == false) {
759+ throw excLine("Expected 'compatibility', read " + s);
760+ }
761+ setCompatibilityAttributes();
762+ return;
763+ }
764+ if (token != '(') {
765+ throw excToken("Expected '(' or '=', read");
766+ }
767+ String op = parseOperation();
768+ parseComma();
769+ long objectClass = parseObjectClass();
770+ parseComma();
771+ long keyAlg = parseKeyAlgorithm();
772+ token = nextToken();
773+ if (token != ')') {
774+ throw excToken("Expected ')', read");
775+ }
776+ parseEquals();
777+ parseOpenBraces();
778+ List<CK_ATTRIBUTE> attributes = new ArrayList<CK_ATTRIBUTE>();
779+ while (true) {
780+ token = nextToken();
781+ if (isCloseBraces(token)) {
782+ break;
783+ }
784+ if (token == TT_EOL) {
785+ continue;
786+ }
787+ if (token != TT_WORD) {
788+ throw excToken("Expected mechanism, read");
789+ }
790+ String attributeName = st.sval;
791+ long attributeId = decodeAttributeName(attributeName);
792+ parseEquals();
793+ String attributeValue = parseWord();
794+ attributes.add(decodeAttributeValue(attributeId, attributeValue));
795+ }
796+ templateManager.addTemplate
797+ (op, objectClass, keyAlg, attributes.toArray(CK_A0));
798+ }
799+
800+ private void setCompatibilityAttributes() {
801+ // all secret keys
802+ templateManager.addTemplate(O_ANY, CKO_SECRET_KEY, PCKK_ANY,
803+ new CK_ATTRIBUTE[] {
804+ TOKEN_FALSE,
805+ SENSITIVE_FALSE,
806+ EXTRACTABLE_TRUE,
807+ ENCRYPT_TRUE,
808+ DECRYPT_TRUE,
809+ WRAP_TRUE,
810+ UNWRAP_TRUE,
811+ });
812+
813+ // generic secret keys are special
814+ // They are used as MAC keys plus for the SSL/TLS (pre)master secrets
815+ templateManager.addTemplate(O_ANY, CKO_SECRET_KEY, CKK_GENERIC_SECRET,
816+ new CK_ATTRIBUTE[] {
817+ SIGN_TRUE,
818+ VERIFY_TRUE,
819+ ENCRYPT_NULL,
820+ DECRYPT_NULL,
821+ WRAP_NULL,
822+ UNWRAP_NULL,
823+ DERIVE_TRUE,
824+ });
825+
826+ // all private and public keys
827+ templateManager.addTemplate(O_ANY, CKO_PRIVATE_KEY, PCKK_ANY,
828+ new CK_ATTRIBUTE[] {
829+ TOKEN_FALSE,
830+ SENSITIVE_FALSE,
831+ EXTRACTABLE_TRUE,
832+ });
833+ templateManager.addTemplate(O_ANY, CKO_PUBLIC_KEY, PCKK_ANY,
834+ new CK_ATTRIBUTE[] {
835+ TOKEN_FALSE,
836+ });
837+
838+ // additional attributes for RSA private keys
839+ templateManager.addTemplate(O_ANY, CKO_PRIVATE_KEY, CKK_RSA,
840+ new CK_ATTRIBUTE[] {
841+ DECRYPT_TRUE,
842+ SIGN_TRUE,
843+ SIGN_RECOVER_TRUE,
844+ UNWRAP_TRUE,
845+ });
846+ // additional attributes for RSA public keys
847+ templateManager.addTemplate(O_ANY, CKO_PUBLIC_KEY, CKK_RSA,
848+ new CK_ATTRIBUTE[] {
849+ ENCRYPT_TRUE,
850+ VERIFY_TRUE,
851+ VERIFY_RECOVER_TRUE,
852+ WRAP_TRUE,
853+ });
854+
855+ // additional attributes for DSA private keys
856+ templateManager.addTemplate(O_ANY, CKO_PRIVATE_KEY, CKK_DSA,
857+ new CK_ATTRIBUTE[] {
858+ SIGN_TRUE,
859+ });
860+ // additional attributes for DSA public keys
861+ templateManager.addTemplate(O_ANY, CKO_PUBLIC_KEY, CKK_DSA,
862+ new CK_ATTRIBUTE[] {
863+ VERIFY_TRUE,
864+ });
865+
866+ // additional attributes for DH private keys
867+ templateManager.addTemplate(O_ANY, CKO_PRIVATE_KEY, CKK_DH,
868+ new CK_ATTRIBUTE[] {
869+ DERIVE_TRUE,
870+ });
871+
872+ // additional attributes for EC private keys
873+ templateManager.addTemplate(O_ANY, CKO_PRIVATE_KEY, CKK_EC,
874+ new CK_ATTRIBUTE[] {
875+ SIGN_TRUE,
876+ DERIVE_TRUE,
877+ });
878+ // additional attributes for EC public keys
879+ templateManager.addTemplate(O_ANY, CKO_PUBLIC_KEY, CKK_EC,
880+ new CK_ATTRIBUTE[] {
881+ VERIFY_TRUE,
882+ });
883+ }
884+
885+ private final static CK_ATTRIBUTE[] CK_A0 = new CK_ATTRIBUTE[0];
886+
887+ private String parseOperation() throws IOException {
888+ String op = parseWord();
889+ if (op.equals("*")) {
890+ return TemplateManager.O_ANY;
891+ } else if (op.equals("generate")) {
892+ return TemplateManager.O_GENERATE;
893+ } else if (op.equals("import")) {
894+ return TemplateManager.O_IMPORT;
895+ } else {
896+ throw excLine("Unknown operation " + op);
897+ }
898+ }
899+
900+ private long parseObjectClass() throws IOException {
901+ String name = parseWord();
902+ try {
903+ return Functions.getObjectClassId(name);
904+ } catch (IllegalArgumentException e) {
905+ throw excLine("Unknown object class " + name);
906+ }
907+ }
908+
909+ private long parseKeyAlgorithm() throws IOException {
910+ String name = parseWord();
911+ if (isNumber(name)) {
912+ return decodeNumber(name);
913+ } else {
914+ try {
915+ return Functions.getKeyId(name);
916+ } catch (IllegalArgumentException e) {
917+ throw excLine("Unknown key algorithm " + name);
918+ }
919+ }
920+ }
921+
922+ private long decodeAttributeName(String name) throws IOException {
923+ if (isNumber(name)) {
924+ return decodeNumber(name);
925+ } else {
926+ try {
927+ return Functions.getAttributeId(name);
928+ } catch (IllegalArgumentException e) {
929+ throw excLine("Unknown attribute name " + name);
930+ }
931+ }
932+ }
933+
934+ private CK_ATTRIBUTE decodeAttributeValue(long id, String value)
935+ throws IOException {
936+ if (value.equals("null")) {
937+ return new CK_ATTRIBUTE(id);
938+ } else if (value.equals("true")) {
939+ return new CK_ATTRIBUTE(id, true);
940+ } else if (value.equals("false")) {
941+ return new CK_ATTRIBUTE(id, false);
942+ } else if (isByteArray(value)) {
943+ return new CK_ATTRIBUTE(id, decodeByteArray(value));
944+ } else if (isNumber(value)) {
945+ return new CK_ATTRIBUTE(id, Integer.valueOf(decodeNumber(value)));
946+ } else {
947+ throw excLine("Unknown attribute value " + value);
948+ }
949+ }
950+
951+ private void parseNSSArgs(String keyword) throws IOException {
952+ checkDup(keyword);
953+ parseEquals();
954+ int token = nextToken();
955+ if (token != '"') {
956+ throw excToken("Expected quoted string");
957+ }
958+ nssArgs = expand(st.sval);
959+ debug("nssArgs: " + nssArgs);
960+ }
961+
962+ private void parseHandleStartupErrors(String keyword) throws IOException {
963+ checkDup(keyword);
964+ parseEquals();
965+ String val = parseWord();
966+ if (val.equals("ignoreAll")) {
967+ handleStartupErrors = ERR_IGNORE_ALL;
968+ } else if (val.equals("ignoreMissingLibrary")) {
969+ handleStartupErrors = ERR_IGNORE_LIB;
970+ } else if (val.equals("halt")) {
971+ handleStartupErrors = ERR_HALT;
972+ } else {
973+ throw excToken("Invalid value for handleStartupErrors:");
974+ }
975+ debug("handleStartupErrors: " + handleStartupErrors);
976+ }
977+
978+}
979+
980+class ConfigurationException extends IOException {
981+ ConfigurationException(String msg) {
982+ super(msg);
983+ }
984+}