KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > com > sun > security > auth > login > ConfigFile


1 /*
2  * @(#)ConfigFile.java 1.18 03/12/19
3  *
4  * Copyright 2004 Sun Microsystems, Inc. All rights reserved.
5  * SUN PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
6  */

7  
8 package com.sun.security.auth.login;
9
10 import javax.security.auth.AuthPermission JavaDoc;
11 import javax.security.auth.login.AppConfigurationEntry JavaDoc;
12 import java.io.*;
13 import java.util.*;
14 import java.net.URL JavaDoc;
15 import java.text.MessageFormat JavaDoc;
16 import sun.security.util.ResourcesMgr;
17 import sun.security.util.PropertyExpander;
18
19 /**
20  * This class represents a default implementation for
21  * <code>javax.security.auth.login.Configuration</code>.
22  *
23  * <p> This object stores the runtime login configuration representation,
24  * and is the amalgamation of multiple static login
25  * configurations that resides in files.
26  * The algorithm for locating the login configuration file(s) and reading their
27  * information into this <code>Configuration</code> object is:
28  *
29  * <ol>
30  * <li>
31  * Loop through the <code>java.security.Security</code> properties,
32  * <i>login.config.url.1</i>, <i>login.config.url.2</i>, ...,
33  * <i>login.config.url.X</i>. These properties are set
34  * in the Java security properties file, which is located in the file named
35  * &lt;JAVA_HOME&gt;/lib/security/java.security, where &lt;JAVA_HOME&gt;
36  * refers to the directory where the JDK was installed.
37  * Each property value specifies a <code>URL</code> pointing to a
38  * login configuration file to be loaded. Read in and load
39  * each configuration.
40  *
41  * <li>
42  * The <code>java.lang.System</code> property
43  * <i>java.security.auth.login.config</i>
44  * may also be set to a <code>URL</code> pointing to another
45  * login configuration file
46  * (which is the case when a user uses the -D switch at runtime).
47  * If this property is defined, and its use is allowed by the
48  * security property file (the Security property,
49  * <i>policy.allowSystemProperty</i> is set to <i>true</i>),
50  * also load that login configuration.
51  *
52  * <li>
53  * If the <i>java.security.auth.login.config</i> property is defined using
54  * "==" (rather than "="), then ignore all other specified
55  * login configurations and only load this configuration.
56  *
57  * <li>
58  * If no system or security properties were set, try to read from the file,
59  * ${user.home}/.java.login.config, where ${user.home} is the value
60  * represented by the "user.home" System property.
61  * </ol>
62  *
63  * <p> The configuration syntax supported by this implementation
64  * is exactly that syntax specified in the
65  * <code>javax.security.auth.login.Configuration</code> class.
66  *
67  * @version 1.6, 01/14/00
68  * @see javax.security.auth.login.LoginContext
69  */

70 public class ConfigFile extends javax.security.auth.login.Configuration JavaDoc {
71
72     private StreamTokenizer st;
73     private int lookahead;
74     private int linenum;
75     private HashMap configuration;
76     private boolean expandProp = true;
77     private boolean testing = false;
78
79     /**
80      * Create a new <code>Configuration</code> object.
81      */

82     public ConfigFile() {
83     String JavaDoc expandProperties = (String JavaDoc)
84         java.security.AccessController.doPrivileged
85         (new java.security.PrivilegedAction JavaDoc() {
86         public Object JavaDoc run() {
87         return System.getProperty("policy.expandProperties");
88         }
89     });
90
91     if ("false".equals(expandProperties))
92         expandProp = false;
93
94     try {
95         init();
96     } catch (IOException ioe) {
97         throw (SecurityException JavaDoc)
98         new SecurityException JavaDoc(ioe.getMessage()).initCause(ioe);
99     }
100     }
101
102     /**
103      * Read and initialize the entire login Configuration.
104      *
105      * <p>
106      *
107      * @exception IOException if the Configuration can not be initialized. <p>
108      * @exception SecurityException if the caller does not have permission
109      * to initialize the Configuration.
110      */

111     private void init() throws IOException {
112
113     boolean initialized = false;
114     FileReader fr = null;
115     String JavaDoc sep = File.separator;
116
117     // new configuration
118
HashMap newConfig = new HashMap();
119
120     String JavaDoc allowSys = java.security.Security.getProperty
121                         ("policy.allowSystemProperty");
122
123     if ("true".equalsIgnoreCase(allowSys)) {
124         String JavaDoc extra_config = System.getProperty
125                     ("java.security.auth.login.config");
126         if (extra_config != null) {
127         boolean overrideAll = false;
128         if (extra_config.startsWith("=")) {
129             overrideAll = true;
130             extra_config = extra_config.substring(1);
131         }
132         try {
133             extra_config = PropertyExpander.expand(extra_config);
134         } catch (PropertyExpander.ExpandException peee) {
135             MessageFormat JavaDoc form = new MessageFormat JavaDoc
136             (ResourcesMgr.getString
137                 ("Unable to properly expand config",
138                 "sun.security.util.AuthResources"));
139             Object JavaDoc[] source = {extra_config};
140             throw new IOException(form.format(source));
141         }
142
143         URL JavaDoc configURL = null;
144         try {
145             configURL = new URL JavaDoc(extra_config);
146         } catch (java.net.MalformedURLException JavaDoc mue) {
147             File configFile = new File(extra_config);
148             if (configFile.exists()) {
149             configURL = new URL JavaDoc("file:" +
150                     configFile.getCanonicalPath());
151             } else {
152             MessageFormat JavaDoc form = new MessageFormat JavaDoc
153                 (ResourcesMgr.getString
154                 ("extra_config (No such file or directory)",
155                 "sun.security.util.AuthResources"));
156             Object JavaDoc[] source = {extra_config};
157             throw new IOException(form.format(source));
158             }
159         }
160
161         if (testing)
162             System.out.println("reading "+configURL);
163         init(configURL, newConfig);
164         initialized = true;
165         if (overrideAll) {
166             if (testing)
167             System.out.println("overriding other policies!");
168         }
169         }
170     }
171
172     int n = 1;
173     String JavaDoc config_url;
174     while ((config_url = java.security.Security.getProperty
175                     ("login.config.url."+n)) != null) {
176         try {
177         config_url = PropertyExpander.expand
178             (config_url).replace(File.separatorChar, '/');
179         if (testing)
180             System.out.println("\tReading config: " + config_url);
181         init(new URL JavaDoc(config_url), newConfig);
182         initialized = true;
183         } catch (PropertyExpander.ExpandException peee) {
184         MessageFormat JavaDoc form = new MessageFormat JavaDoc
185             (ResourcesMgr.getString
186                 ("Unable to properly expand config",
187                 "sun.security.util.AuthResources"));
188         Object JavaDoc[] source = {config_url};
189         throw new IOException(form.format(source));
190         }
191         n++;
192     }
193
194     if (initialized == false && n == 1 && config_url == null) {
195
196         // get the config from the user's home directory
197
if (testing)
198         System.out.println("\tReading Policy " +
199                 "from ~/.java.login.config");
200         config_url = System.getProperty("user.home");
201         try {
202         init(new URL JavaDoc("file:" + config_url +
203             File.separatorChar + ".java.login.config"),
204             newConfig);
205         } catch (IOException ioe) {
206         throw new IOException(ResourcesMgr.getString
207             ("Unable to locate a login configuration",
208             "sun.security.util.AuthResources"));
209         }
210     }
211
212     configuration = newConfig;
213     }
214
215     private void init(URL JavaDoc config, HashMap newConfig) throws IOException {
216     InputStreamReader isr
217         = new InputStreamReader(getInputStream(config), "UTF-8");
218     readConfig(isr, newConfig);
219     isr.close();
220     }
221
222     /**
223      * Retrieve an entry from the Configuration using an application name
224      * as an index.
225      *
226      * <p>
227      *
228      * @param applicationName the name used to index the Configuration.
229      * @return an array of AppConfigurationEntries which correspond to
230      * the stacked configuration of LoginModules for this
231      * application, or null if this application has no configured
232      * LoginModules.
233      */

234     public AppConfigurationEntry JavaDoc[] getAppConfigurationEntry
235     (String JavaDoc applicationName) {
236
237     LinkedList list = null;
238     synchronized (configuration) {
239         list = (LinkedList)configuration.get(applicationName);
240     }
241
242     if (list == null || list.size() == 0)
243         return null;
244
245     AppConfigurationEntry JavaDoc[] entries =
246                 new AppConfigurationEntry JavaDoc[list.size()];
247     Iterator iterator = list.iterator();
248     for (int i = 0; iterator.hasNext(); i++) {
249         AppConfigurationEntry JavaDoc e = (AppConfigurationEntry JavaDoc)iterator.next();
250         entries[i] = new AppConfigurationEntry JavaDoc(e.getLoginModuleName(),
251                         e.getControlFlag(),
252                         e.getOptions());
253     }
254     return entries;
255     }
256
257     /**
258      * Refresh and reload the Configuration by re-reading all of the
259      * login configurations.
260      *
261      * <p>
262      *
263      * @exception SecurityException if the caller does not have permission
264      * to refresh the Configuration.
265      */

266     public synchronized void refresh() {
267
268     java.lang.SecurityManager JavaDoc sm = System.getSecurityManager();
269     if (sm != null)
270         sm.checkPermission(new AuthPermission JavaDoc("refreshLoginConfiguration"));
271
272     java.security.AccessController.doPrivileged
273         (new java.security.PrivilegedAction JavaDoc() {
274         public Object JavaDoc run() {
275         try {
276             init();
277         } catch (java.io.IOException JavaDoc ioe) {
278             throw new SecurityException JavaDoc(ioe.getLocalizedMessage());
279         }
280         return null;
281         }
282     });
283     }
284
285     private void readConfig(Reader reader, HashMap newConfig)
286     throws IOException {
287
288     int linenum = 1;
289  
290     if (!(reader instanceof BufferedReader))
291         reader = new BufferedReader(reader);
292  
293     st = new StreamTokenizer(reader);
294     st.quoteChar('"');
295     st.wordChars('$', '$');
296     st.wordChars('_', '_');
297     st.wordChars('-', '-');
298     st.lowerCaseMode(false);
299     st.slashSlashComments(true);
300     st.slashStarComments(true);
301     st.eolIsSignificant(true);
302  
303     lookahead = nextToken();
304     while (lookahead != StreamTokenizer.TT_EOF) {
305  
306         if (testing)
307         System.out.print("\tReading next config entry: ");
308         parseLoginEntry(newConfig);
309     }
310     }
311
312     private void parseLoginEntry(HashMap newConfig) throws IOException {
313  
314     String JavaDoc appName;
315     String JavaDoc moduleClass;
316     String JavaDoc sflag;
317     AppConfigurationEntry.LoginModuleControlFlag JavaDoc controlFlag;
318     LinkedList configEntries = new LinkedList();
319  
320     // application name
321
appName = st.sval;
322     lookahead = nextToken();
323  
324     if (testing)
325         System.out.println("appName = " + appName);
326  
327     match("{");
328  
329     // get the modules
330
while (peek("}") == false) {
331         HashSet argSet = new HashSet();
332  
333         // get the module class name
334
moduleClass = match("module class name");
335  
336         // controlFlag (required, optional, etc)
337
sflag = match("controlFlag");
338         if (sflag.equalsIgnoreCase("REQUIRED"))
339         controlFlag =
340             AppConfigurationEntry.LoginModuleControlFlag.REQUIRED;
341         else if (sflag.equalsIgnoreCase("REQUISITE"))
342         controlFlag =
343             AppConfigurationEntry.LoginModuleControlFlag.REQUISITE;
344         else if (sflag.equalsIgnoreCase("SUFFICIENT"))
345         controlFlag =
346             AppConfigurationEntry.LoginModuleControlFlag.SUFFICIENT;
347         else if (sflag.equalsIgnoreCase("OPTIONAL"))
348         controlFlag =
349             AppConfigurationEntry.LoginModuleControlFlag.OPTIONAL;
350         else {
351         MessageFormat JavaDoc form = new MessageFormat JavaDoc(ResourcesMgr.getString
352             ("Configuration Error:\n\tInvalid control flag, flag",
353             "sun.security.util.AuthResources"));
354         Object JavaDoc[] source = {sflag};
355         throw new IOException(form.format(source));
356         }
357  
358         // get the args
359
HashMap options = new HashMap();
360         String JavaDoc key;
361         String JavaDoc value;
362         while (peek(";") == false) {
363         key = match("option key");
364         match("=");
365         try {
366             value = expand(match("option value"));
367         } catch (PropertyExpander.ExpandException peee) {
368             throw new IOException(peee.getLocalizedMessage());
369         }
370         options.put(key, value);
371         }
372  
373         lookahead = nextToken();
374  
375         // create the new element
376
if (testing) {
377         System.out.print("\t\t" + moduleClass + ", " + sflag);
378         java.util.Iterator JavaDoc i = options.keySet().iterator();
379         while (i.hasNext()) {
380             key = (String JavaDoc)i.next();
381             System.out.print(", " +
382                     key +
383                     "=" +
384                     (String JavaDoc)options.get(key));
385         }
386         System.out.println("");
387         }
388         AppConfigurationEntry JavaDoc entry = new AppConfigurationEntry JavaDoc
389                             (moduleClass,
390                             controlFlag,
391                             options);
392         configEntries.add(entry);
393     }
394
395     match("}");
396     match(";");
397  
398     // add this configuration entry
399
if (newConfig.containsKey(appName)) {
400         MessageFormat JavaDoc form = new MessageFormat JavaDoc(ResourcesMgr.getString
401         ("Configuration Error:\n\t" +
402             "Can not specify multiple entries for appName",
403         "sun.security.util.AuthResources"));
404         Object JavaDoc[] source = {appName};
405         throw new IOException(form.format(source));
406     }
407     newConfig.put(appName, configEntries);
408     if (testing)
409         System.out.println("\t\t***Added entry for " +
410                 appName + " to overall configuration***");
411     }
412
413     private String JavaDoc match(String JavaDoc expect) throws IOException {
414  
415     String JavaDoc value = null;
416  
417     switch(lookahead) {
418     case StreamTokenizer.TT_EOF:
419  
420         MessageFormat JavaDoc form1 = new MessageFormat JavaDoc(ResourcesMgr.getString
421         ("Configuration Error:\n\texpected [expect], " +
422             "read [end of file]",
423         "sun.security.util.AuthResources"));
424         Object JavaDoc[] source1 = {expect};
425         throw new IOException(form1.format(source1));
426  
427     case '"':
428     case StreamTokenizer.TT_WORD:
429
430         if (expect.equalsIgnoreCase("module class name") ||
431         expect.equalsIgnoreCase("controlFlag") ||
432         expect.equalsIgnoreCase("option key") ||
433         expect.equalsIgnoreCase("option value")) {
434         value = st.sval;
435         lookahead = nextToken();
436         } else {
437         MessageFormat JavaDoc form = new MessageFormat JavaDoc(ResourcesMgr.getString
438             ("Configuration Error:\n\tLine line: " +
439                 "expected [expect], found [value]",
440             "sun.security.util.AuthResources"));
441         Object JavaDoc[] source = {new Integer JavaDoc(linenum), expect, st.sval};
442         throw new IOException(form.format(source));
443         }
444         break;
445  
446     case '{':
447  
448         if (expect.equalsIgnoreCase("{")) {
449         lookahead = nextToken();
450         } else {
451         MessageFormat JavaDoc form = new MessageFormat JavaDoc(ResourcesMgr.getString
452             ("Configuration Error:\n\tLine line: expected [expect]",
453             "sun.security.util.AuthResources"));
454         Object JavaDoc[] source = {new Integer JavaDoc(linenum), expect, st.sval};
455         throw new IOException(form.format(source));
456         }
457         break;
458
459     case ';':
460
461         if (expect.equalsIgnoreCase(";")) {
462         lookahead = nextToken();
463         } else {
464         MessageFormat JavaDoc form = new MessageFormat JavaDoc(ResourcesMgr.getString
465             ("Configuration Error:\n\tLine line: expected [expect]",
466             "sun.security.util.AuthResources"));
467         Object JavaDoc[] source = {new Integer JavaDoc(linenum), expect, st.sval};
468         throw new IOException(form.format(source));
469         }
470         break;
471  
472     case '}':
473  
474         if (expect.equalsIgnoreCase("}")) {
475         lookahead = nextToken();
476         } else {
477         MessageFormat JavaDoc form = new MessageFormat JavaDoc(ResourcesMgr.getString
478             ("Configuration Error:\n\tLine line: expected [expect]",
479             "sun.security.util.AuthResources"));
480         Object JavaDoc[] source = {new Integer JavaDoc(linenum), expect, st.sval};
481         throw new IOException(form.format(source));
482         }
483         break;
484
485     case '=':
486
487         if (expect.equalsIgnoreCase("=")) {
488         lookahead = nextToken();
489         } else {
490         MessageFormat JavaDoc form = new MessageFormat JavaDoc(ResourcesMgr.getString
491             ("Configuration Error:\n\tLine line: expected [expect]",
492             "sun.security.util.AuthResources"));
493         Object JavaDoc[] source = {new Integer JavaDoc(linenum), expect, st.sval};
494         throw new IOException(form.format(source));
495         }
496         break;
497  
498     default:
499         MessageFormat JavaDoc form = new MessageFormat JavaDoc(ResourcesMgr.getString
500             ("Configuration Error:\n\tLine line: " +
501                 "expected [expect], found [value]",
502             "sun.security.util.AuthResources"));
503         Object JavaDoc[] source = {new Integer JavaDoc(linenum), expect, st.sval};
504         throw new IOException(form.format(source));
505     }
506     return value;
507     }
508
509     private boolean peek(String JavaDoc expect) {
510     boolean found = false;
511  
512     switch (lookahead) {
513     case ',':
514         if (expect.equalsIgnoreCase(","))
515         found = true;
516         break;
517     case ';':
518         if (expect.equalsIgnoreCase(";"))
519         found = true;
520         break;
521     case '{':
522         if (expect.equalsIgnoreCase("{"))
523         found = true;
524         break;
525     case '}':
526         if (expect.equalsIgnoreCase("}"))
527         found = true;
528         break;
529     default:
530     }
531     return found;
532     }
533
534     private int nextToken() throws IOException {
535     int tok;
536     while ((tok = st.nextToken()) == StreamTokenizer.TT_EOL) {
537         linenum++;
538     }
539     return tok;
540     }
541
542     /*
543      * Fast path reading from file urls in order to avoid calling
544      * FileURLConnection.connect() which can be quite slow the first time
545      * it is called. We really should clean up FileURLConnection so that
546      * this is not a problem but in the meantime this fix helps reduce
547      * start up time noticeably for the new launcher. -- DAC
548      */

549     private InputStream getInputStream(URL JavaDoc url) throws IOException {
550     if ("file".equals(url.getProtocol())) {
551         String JavaDoc path = url.getFile().replace('/', File.separatorChar);
552         return new FileInputStream(path);
553     } else {
554         return url.openStream();
555     }
556     }
557
558     private String JavaDoc expand(String JavaDoc value)
559     throws PropertyExpander.ExpandException, IOException {
560
561     if ("".equals(value)) {
562         return value;
563     }
564
565     if (expandProp) {
566
567         String JavaDoc s = PropertyExpander.expand(value);
568
569         if (s == null || s.length() == 0) {
570         MessageFormat JavaDoc form = new MessageFormat JavaDoc(ResourcesMgr.getString
571             ("Configuration Error:\n\tLine line: " +
572             "system property [value] expanded to empty value",
573             "sun.security.util.AuthResources"));
574         Object JavaDoc[] source = {new Integer JavaDoc(linenum), value};
575         throw new IOException(form.format(source));
576         }
577         return s;
578     } else {
579         return value;
580     }
581     }
582 }
583
Popular Tags