OpenCores
URL https://opencores.org/ocsvn/openrisc/openrisc/trunk

Subversion Repositories openrisc

[/] [openrisc/] [trunk/] [gnu-dev/] [or1k-gcc/] [libjava/] [classpath/] [gnu/] [javax/] [security/] [auth/] [login/] [ConfigFileParser.java] - Blame information for rev 769

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 769 jeremybenn
/* ConfigFileParser.java -- JAAS Login Configuration default syntax parser
2
   Copyright (C) 2006 Free Software Foundation, Inc.
3
 
4
This file is part of GNU Classpath.
5
 
6
GNU Classpath is free software; you can redistribute it and/or modify
7
it under the terms of the GNU General Public License as published by
8
the Free Software Foundation; either version 2, or (at your option)
9
any later version.
10
 
11
GNU Classpath is distributed in the hope that it will be useful, but
12
WITHOUT ANY WARRANTY; without even the implied warranty of
13
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14
General Public License for more details.
15
 
16
You should have received a copy of the GNU General Public License
17
along with GNU Classpath; see the file COPYING.  If not, write to the
18
Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
19
02110-1301 USA.
20
 
21
Linking this library statically or dynamically with other modules is
22
making a combined work based on this library.  Thus, the terms and
23
conditions of the GNU General Public License cover the whole
24
combination.
25
 
26
As a special exception, the copyright holders of this library give you
27
permission to link this library with independent modules to produce an
28
executable, regardless of the license terms of these independent
29
modules, and to copy and distribute the resulting executable under
30
terms of your choice, provided that you also meet, for each linked
31
independent module, the terms and conditions of the license of that
32
module.  An independent module is a module which is not derived from
33
or based on this library.  If you modify this library, you may extend
34
this exception to your version of the library, but you are not
35
obligated to do so.  If you do not wish to do so, delete this
36
exception statement from your version. */
37
 
38
 
39
package gnu.javax.security.auth.login;
40
 
41
import gnu.java.security.Configuration;
42
 
43
import java.io.IOException;
44
import java.io.Reader;
45
import java.util.ArrayList;
46
import java.util.HashMap;
47
import java.util.List;
48
import java.util.Map;
49
import java.util.logging.Logger;
50
 
51
import javax.security.auth.login.AppConfigurationEntry;
52
 
53
/**
54
 * A parser that knows how to interpret JAAS Login Module Configuration files
55
 * written in the <i>default syntax</i> which is interpreted as adhering to
56
 * the following grammar:
57
 *
58
 * <pre>
59
 *   CONFIG              ::= APP_OR_OTHER_ENTRY+
60
 *   APP_OR_OTHER_ENTRY  ::= APP_NAME_OR_OTHER JAAS_CONFIG_BLOCK
61
 *   APP_NAME_OR_OTHER   ::= APP_NAME
62
 *                         | 'other'
63
 *   JAAS_CONFIG_BLOCK   ::= '{' (LOGIN_MODULE_ENTRY ';')+ '}' ';'
64
 *   LOGIN_MODULE_ENTRY  ::= MODULE_CLASS FLAG MODULE_OPTION* ';'
65
 *   FLAG                ::= 'required'
66
 *                         | 'requisite'
67
 *                         | 'sufficient'
68
 *                         | 'optional'
69
 *   MODULE_OPTION       ::= PARAM_NAME '=' PARAM_VALUE
70
 *
71
 *   APP_NAME     ::= JAVA_IDENTIFIER
72
 *   MODULE_CLASS ::= JAVA_IDENTIFIER ('.' JAVA_IDENTIFIER)*
73
 *   PARAM_NAME   ::= STRING
74
 *   PARAM_VALUE  ::= '"' STRING '"' | ''' STRING ''' | STRING
75
 * </pre>
76
 *
77
 * <p>This parser handles UTF-8 entities when used as APP_NAME and PARAM_VALUE.
78
 * It also checks for the use of Java identifiers used in MODULE_CLASS, thus
79
 * minimizing the risks of having {@link java.lang.ClassCastException}s thrown
80
 * at runtime due to syntactically invalid names.</p>
81
 *
82
 * <p>In the above context, a JAVA_IDENTIFIER is a sequence of tokens,
83
 * separated by the character '.'. Each of these tokens obeys the following:</p>
84
 *
85
 * <ol>
86
 *   <li>its first character yields <code>true</code> when used as an input to
87
 *   the {@link java.lang.Character#isJavaIdentifierStart(char)}, and</li>
88
 *   <li>all remaining characters, yield <code>true</code> when used as an
89
 *   input to {@link java.lang.Character#isJavaIdentifierPart(char)}.</li>
90
 * </ol>
91
 */
92
public final class ConfigFileParser
93
{
94
  private static final Logger log = Logger.getLogger(ConfigFileParser.class.getName());
95
  private ConfigFileTokenizer cft;
96
  private Map map = new HashMap();
97
 
98
  // default 0-arguments constructor
99
 
100
  /**
101
   * Returns the parse result as a {@link Map} where the keys are application
102
   * names, and the entries are {@link List}s of {@link AppConfigurationEntry}
103
   * entries, one for each login module entry, in the order they were
104
   * encountered, for that application name in the just parsed configuration
105
   * file.
106
   */
107
  public Map getLoginModulesMap()
108
  {
109
    return map;
110
  }
111
 
112
  /**
113
   * Parses the {@link Reader}'s contents assuming it is in the <i>default
114
   * syntax</i>.
115
   *
116
   * @param r the {@link Reader} whose contents are assumed to be a JAAS Login
117
   * Configuration Module file written in the <i>default syntax</i>.
118
   * @throws IOException if an exception occurs while parsing the input.
119
   */
120
  public void parse(Reader r) throws IOException
121
  {
122
    initParser(r);
123
 
124
    while (parseAppOrOtherEntry())
125
      {
126
        /* do nothing */
127
      }
128
  }
129
 
130
  private void initParser(Reader r) throws IOException
131
  {
132
    map.clear();
133
 
134
    cft = new ConfigFileTokenizer(r);
135
  }
136
 
137
  /**
138
   * @return <code>true</code> if an APP_OR_OTHER_ENTRY was correctly parsed.
139
   * Returns <code>false</code> otherwise.
140
   * @throws IOException if an exception occurs while parsing the input.
141
   */
142
  private boolean parseAppOrOtherEntry() throws IOException
143
  {
144
    int c = cft.nextToken();
145
    if (c == ConfigFileTokenizer.TT_EOF)
146
      return false;
147
 
148
    if (c != ConfigFileTokenizer.TT_WORD)
149
      {
150
        cft.pushBack();
151
        return false;
152
      }
153
 
154
    String appName = cft.sval;
155
    if (Configuration.DEBUG)
156
      log.fine("APP_NAME_OR_OTHER = " + appName);
157
    if (cft.nextToken() != '{')
158
      abort("Missing '{' after APP_NAME_OR_OTHER");
159
 
160
    List lmis = new ArrayList();
161
    while (parseACE(lmis))
162
      {
163
        /* do nothing */
164
      }
165
 
166
    c = cft.nextToken();
167
    if (c != '}')
168
      abort("Was expecting '}' but found " + (char) c);
169
 
170
    c = cft.nextToken();
171
    if (c != ';')
172
      abort("Was expecting ';' but found " + (char) c);
173
 
174
    List listOfACEs = (List) map.get(appName);
175
    if (listOfACEs == null)
176
      {
177
        listOfACEs = new ArrayList();
178
        map.put(appName, listOfACEs);
179
      }
180
    listOfACEs.addAll(lmis);
181
    return !appName.equalsIgnoreCase("other");
182
  }
183
 
184
  /**
185
   * @return <code>true</code> if a LOGIN_MODULE_ENTRY was correctly parsed.
186
   * Returns <code>false</code> otherwise.
187
   * @throws IOException if an exception occurs while parsing the input.
188
   */
189
  private boolean parseACE(List listOfACEs) throws IOException
190
  {
191
    int c = cft.nextToken();
192
    if (c != ConfigFileTokenizer.TT_WORD)
193
      {
194
        cft.pushBack();
195
        return false;
196
      }
197
 
198
    String clazz = validateClassName(cft.sval);
199
    if (Configuration.DEBUG)
200
      log.fine("MODULE_CLASS = " + clazz);
201
 
202
    if (cft.nextToken() != ConfigFileTokenizer.TT_WORD)
203
      abort("Was expecting FLAG but found none");
204
 
205
    String flag = cft.sval;
206
    if (Configuration.DEBUG)
207
      log.fine("DEBUG: FLAG = " + flag);
208
    AppConfigurationEntry.LoginModuleControlFlag f = null;
209
    if (flag.equalsIgnoreCase("required"))
210
      f = AppConfigurationEntry.LoginModuleControlFlag.REQUIRED;
211
    else if (flag.equalsIgnoreCase("requisite"))
212
      f = AppConfigurationEntry.LoginModuleControlFlag.REQUISITE;
213
    else if (flag.equalsIgnoreCase("sufficient"))
214
      f = AppConfigurationEntry.LoginModuleControlFlag.SUFFICIENT;
215
    else if (flag.equalsIgnoreCase("optional"))
216
      f = AppConfigurationEntry.LoginModuleControlFlag.OPTIONAL;
217
    else
218
      abort("Unknown Flag: " + flag);
219
 
220
    Map options = new HashMap();
221
    String paramName, paramValue;
222
    c = cft.nextToken();
223
    while (c != ';')
224
      {
225
        if (c != ConfigFileTokenizer.TT_WORD)
226
          abort("Was expecting PARAM_NAME but got '" + ((char) c) + "'");
227
 
228
        paramName = cft.sval;
229
        if (Configuration.DEBUG)
230
          log.fine("PARAM_NAME = " + paramName);
231
        if (cft.nextToken() != '=')
232
          abort("Missing '=' after PARAM_NAME");
233
 
234
        c = cft.nextToken();
235
        if (c != '"' && c != '\'')
236
          {
237
          if (Configuration.DEBUG)
238
            log.fine("Was expecting a quoted string but got no quote character."
239
                     + " Assume unquoted string");
240
          }
241
        paramValue = expandParamValue(cft.sval);
242
        if (Configuration.DEBUG)
243
          log.fine("PARAM_VALUE = " + paramValue);
244
        options.put(paramName, paramValue);
245
 
246
        c = cft.nextToken();
247
      }
248
    AppConfigurationEntry ace = new AppConfigurationEntry(clazz, f, options);
249
    if (Configuration.DEBUG)
250
      log.fine("LOGIN_MODULE_ENTRY = " + ace);
251
    listOfACEs.add(ace);
252
    return true;
253
  }
254
 
255
  private void abort(String m) throws IOException
256
  {
257
    if (Configuration.DEBUG)
258
      {
259
        log.fine(m);
260
        log.fine("Map (so far) = " + String.valueOf(map));
261
      }
262
    throw new IOException(m);
263
  }
264
 
265
  private String validateClassName(String cn) throws IOException
266
  {
267
    if (cn.startsWith(".") || cn.endsWith("."))
268
      abort("MODULE_CLASS MUST NOT start or end with a '.'");
269
 
270
    String[] tokens = cn.split("\\.");
271
    for (int i = 0; i < tokens.length; i++)
272
      {
273
        String t = tokens[i];
274
        if (! Character.isJavaIdentifierStart(t.charAt(0)))
275
          abort("Class name [" + cn
276
                + "] contains an invalid sub-package identifier: " + t);
277
 
278
        // we dont check the rest of the characters for isJavaIdentifierPart()
279
        // because that's what the tokenizer does.
280
      }
281
 
282
    return cn;
283
  }
284
 
285
  /**
286
   * The documentation of the {@link javax.security.auth.login.Configuration}
287
   * states that: <i>"...If a String in the form, ${system.property}, occurs in
288
   * the value, it will be expanded to the value of the system property."</i>.
289
   * This method ensures this is the case. If such a string can not be expanded
290
   * then it is left AS IS, assuming the LoginModule knows what to do with it.
291
   *
292
   * <p><b>IMPORTANT</b>: This implementation DOES NOT handle embedded ${}
293
   * constructs.
294
   *
295
   * @param s the raw parameter value, incl. eventually strings of the form
296
   * <code>${system.property}</code>.
297
   * @return the input string with every occurence of
298
   * <code>${system.property}</code> replaced with the value of the
299
   * corresponding System property at the time of this method invocation. If
300
   * the string is not a known System property name, then the complete sequence
301
   * (incl. the ${} characters are passed AS IS.
302
   */
303
  private String expandParamValue(String s)
304
  {
305
    String result = s;
306
    try
307
      {
308
        int searchNdx = 0;
309
        while (searchNdx < result.length())
310
          {
311
            int i = s.indexOf("${", searchNdx);
312
            if (i == -1)
313
              break;
314
 
315
            int j = s.indexOf("}", i + 2);
316
            if (j == -1)
317
              {
318
                if (Configuration.DEBUG)
319
                  log.fine("Found a ${ prefix with no } suffix. Ignore");
320
                break;
321
              }
322
 
323
            String sysPropName = s.substring(i + 2, j);
324
            if (Configuration.DEBUG)
325
              log.fine("Found a reference to System property " + sysPropName);
326
            String sysPropValue = System.getProperty(sysPropName);
327
            if (Configuration.DEBUG)
328
              log.fine("Resolved " + sysPropName + " to '" + sysPropValue + "'");
329
            if (sysPropValue != null)
330
              {
331
                result = s.substring(0, i) + sysPropValue + s.substring(j + 1);
332
                searchNdx = i + sysPropValue.length();
333
              }
334
            else
335
              searchNdx = j + 1;
336
          }
337
      }
338
    catch (Exception x)
339
      {
340
        if (Configuration.DEBUG)
341
          log.fine("Exception (ignored) while expanding " + s + ": " + x);
342
      }
343
 
344
    return result;
345
  }
346
}

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.