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

Subversion Repositories scarts

[/] [scarts/] [trunk/] [toolchain/] [scarts-gcc/] [gcc-4.1.1/] [libjava/] [classpath/] [gnu/] [java/] [security/] [PolicyFile.java] - Blame information for rev 14

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 14 jlechner
/* PolicyFile.java -- policy file reader
2
   Copyright (C) 2004, 2005  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
package gnu.java.security;
39
 
40
import gnu.classpath.SystemProperties;
41
import gnu.classpath.debug.Component;
42
import gnu.classpath.debug.SystemLogger;
43
 
44
import java.io.File;
45
import java.io.IOException;
46
import java.io.InputStreamReader;
47
import java.io.StreamTokenizer;
48
import java.lang.reflect.Constructor;
49
import java.net.MalformedURLException;
50
import java.net.URL;
51
import java.security.AccessController;
52
import java.security.CodeSource;
53
import java.security.KeyStore;
54
import java.security.KeyStoreException;
55
import java.security.Permission;
56
import java.security.PermissionCollection;
57
import java.security.Permissions;
58
import java.security.Policy;
59
import java.security.Principal;
60
import java.security.PrivilegedActionException;
61
import java.security.PrivilegedExceptionAction;
62
import java.security.Security;
63
import java.security.UnresolvedPermission;
64
import java.security.cert.Certificate;
65
import java.security.cert.X509Certificate;
66
import java.util.Enumeration;
67
import java.util.HashMap;
68
import java.util.Iterator;
69
import java.util.LinkedList;
70
import java.util.List;
71
import java.util.Map;
72
import java.util.StringTokenizer;
73
import java.util.logging.Logger;
74
 
75
/**
76
 * An implementation of a {@link java.security.Policy} object whose
77
 * permissions are specified by a <em>policy file</em>.
78
 *
79
 * <p>The approximate syntax of policy files is:</p>
80
 *
81
 * <pre>
82
 * policyFile ::= keystoreOrGrantEntries ;
83
 *
84
 * keystoreOrGrantEntries ::= keystoreOrGrantEntry |
85
 *                            keystoreOrGrantEntries keystoreOrGrantEntry |
86
 *                            EMPTY ;
87
 *
88
 * keystoreOrGrantEntry ::= keystoreEntry | grantEntry ;
89
 *
90
 * keystoreEntry ::= "keystore" keystoreUrl ';' |
91
 *                   "keystore" keystoreUrl ',' keystoreAlgorithm ';' ;
92
 *
93
 * keystoreUrl ::= URL ;
94
 * keystoreAlgorithm ::= STRING ;
95
 *
96
 * grantEntry ::= "grant" domainParameters '{' permissions '}' ';'
97
 *
98
 * domainParameters ::= domainParameter |
99
 *                      domainParameter ',' domainParameters ;
100
 *
101
 * domainParameter ::= "signedBy" signerNames |
102
 *                     "codeBase" codeBaseUrl |
103
 *                     "principal" principalClassName principalName |
104
 *                     "principal" principalName ;
105
 *
106
 * signerNames ::= quotedString ;
107
 * codeBaseUrl ::= URL ;
108
 * principalClassName ::= STRING ;
109
 * principalName ::= quotedString ;
110
 *
111
 * quotedString ::= quoteChar STRING quoteChar ;
112
 * quoteChar ::= '"' | '\'';
113
 *
114
 * permissions ::= permission | permissions permission ;
115
 *
116
 * permission ::= "permission" permissionClassName permissionTarget permissionAction |
117
 *                "permission" permissionClassName permissionTarget |
118
 *                "permission" permissionClassName;
119
 * </pre>
120
 *
121
 * <p>Comments are either form of Java comments. Keystore entries only
122
 * affect subsequent grant entries, so if a grant entry preceeds a
123
 * keystore entry, that grant entry is not affected by that keystore
124
 * entry. Certian instances of <code>${property-name}</code> will be
125
 * replaced with <code>System.getProperty("property-name")</code> in
126
 * quoted strings.</p>
127
 *
128
 * <p>This class will load the following files when created or
129
 * refreshed, in order:</p>
130
 *
131
 * <ol>
132
 * <li>The file <code>${java.home}/lib/security/java.policy</code>.</li>
133
 * <li>All URLs specified by security properties
134
 * <code>"policy.file.<i>n</i>"</code>, for increasing <i>n</i>
135
 * starting from 1. The sequence stops at the first undefined
136
 * property, so you must set <code>"policy.file.1"</code> if you also
137
 * set <code>"policy.file.2"</code>, and so on.</li>
138
 * <li>The URL specified by the property
139
 * <code>"java.security.policy"</code>.</li>
140
 * </ol>
141
 *
142
 * @author Casey Marshall (csm@gnu.org)
143
 * @see java.security.Policy
144
 */
145
public final class PolicyFile extends Policy
146
{
147
 
148
  // Constants and fields.
149
  // -------------------------------------------------------------------------
150
 
151
  private static final Logger logger = SystemLogger.SYSTEM;
152
 
153
  private static final String DEFAULT_POLICY =
154
    SystemProperties.getProperty("java.home")
155
    + SystemProperties.getProperty("file.separator") + "lib"
156
    + SystemProperties.getProperty("file.separator") + "security"
157
    + SystemProperties.getProperty("file.separator") + "java.policy";
158
  private static final String DEFAULT_USER_POLICY =
159
    SystemProperties.getProperty ("user.home") +
160
    SystemProperties.getProperty ("file.separator") + ".java.policy";
161
 
162
  private final Map cs2pc;
163
 
164
  // Constructors.
165
  // -------------------------------------------------------------------------
166
 
167
  public PolicyFile()
168
  {
169
    cs2pc = new HashMap();
170
    refresh();
171
  }
172
 
173
  // Instance methods.
174
  // -------------------------------------------------------------------------
175
 
176
  public PermissionCollection getPermissions(CodeSource codeSource)
177
  {
178
    Permissions perms = new Permissions();
179
    for (Iterator it = cs2pc.entrySet().iterator(); it.hasNext(); )
180
      {
181
        Map.Entry e = (Map.Entry) it.next();
182
        CodeSource cs = (CodeSource) e.getKey();
183
        if (cs.implies(codeSource))
184
          {
185
            logger.log (Component.POLICY, "{0} -> {1}", new Object[]
186
              { cs, codeSource });
187
            PermissionCollection pc = (PermissionCollection) e.getValue();
188
            for (Enumeration ee = pc.elements(); ee.hasMoreElements(); )
189
              {
190
                perms.add((Permission) ee.nextElement());
191
              }
192
          }
193
        else
194
          logger.log (Component.POLICY, "{0} !-> {1}", new Object[]
195
            { cs, codeSource });
196
      }
197
    logger.log (Component.POLICY, "returning permissions {0} for {1}",
198
                new Object[] { perms, codeSource });
199
    return perms;
200
  }
201
 
202
  public void refresh()
203
  {
204
    cs2pc.clear();
205
    final List policyFiles = new LinkedList();
206
    try
207
      {
208
        policyFiles.add (new File (DEFAULT_POLICY).toURL());
209
        policyFiles.add (new File (DEFAULT_USER_POLICY).toURL ());
210
 
211
        AccessController.doPrivileged(
212
          new PrivilegedExceptionAction()
213
          {
214
            public Object run() throws Exception
215
            {
216
              String allow = Security.getProperty ("policy.allowSystemProperty");
217
              if (allow == null || Boolean.getBoolean (allow))
218
                {
219
                  String s = SystemProperties.getProperty ("java.security.policy");
220
                  logger.log (Component.POLICY, "java.security.policy={0}", s);
221
                  if (s != null)
222
                    {
223
                      boolean only = s.startsWith ("=");
224
                      if (only)
225
                        s = s.substring (1);
226
                      policyFiles.clear ();
227
                      policyFiles.add (new URL (s));
228
                      if (only)
229
                        return null;
230
                    }
231
                }
232
              for (int i = 1; ; i++)
233
                {
234
                  String pname = "policy.url." + i;
235
                  String s = Security.getProperty (pname);
236
                  logger.log (Component.POLICY, "{0}={1}", new Object []
237
                    { pname, s });
238
                  if (s == null)
239
                    break;
240
                  policyFiles.add (new URL (s));
241
                }
242
              return null;
243
            }
244
          });
245
      }
246
    catch (PrivilegedActionException pae)
247
      {
248
        logger.log (Component.POLICY, "reading policy properties", pae);
249
      }
250
    catch (MalformedURLException mue)
251
      {
252
        logger.log (Component.POLICY, "setting default policies", mue);
253
      }
254
 
255
    logger.log (Component.POLICY, "building policy from URLs {0}",
256
                policyFiles);
257
    for (Iterator it = policyFiles.iterator(); it.hasNext(); )
258
      {
259
        try
260
          {
261
            URL url = (URL) it.next();
262
            parse(url);
263
          }
264
        catch (IOException ioe)
265
          {
266
            logger.log (Component.POLICY, "reading policy", ioe);
267
          }
268
      }
269
  }
270
 
271
  public String toString()
272
  {
273
    return super.toString() + " [ " + cs2pc.toString() + " ]";
274
  }
275
 
276
  // Own methods.
277
  // -------------------------------------------------------------------------
278
 
279
  private static final int STATE_BEGIN = 0;
280
  private static final int STATE_GRANT = 1;
281
  private static final int STATE_PERMS = 2;
282
 
283
  /**
284
   * Parse a policy file, incorporating the permission definitions
285
   * described therein.
286
   *
287
   * @param url The URL of the policy file to read.
288
   * @throws IOException if an I/O error occurs, or if the policy file
289
   * cannot be parsed.
290
   */
291
  private void parse(final URL url) throws IOException
292
  {
293
    logger.log (Component.POLICY, "reading policy file from {0}", url);
294
    final StreamTokenizer in = new StreamTokenizer(new InputStreamReader(url.openStream()));
295
    in.resetSyntax();
296
    in.slashSlashComments(true);
297
    in.slashStarComments(true);
298
    in.wordChars('A', 'Z');
299
    in.wordChars('a', 'z');
300
    in.wordChars('0', '9');
301
    in.wordChars('.', '.');
302
    in.wordChars('_', '_');
303
    in.wordChars('$', '$');
304
    in.whitespaceChars(' ', ' ');
305
    in.whitespaceChars('\t', '\t');
306
    in.whitespaceChars('\f', '\f');
307
    in.whitespaceChars('\n', '\n');
308
    in.whitespaceChars('\r', '\r');
309
    in.quoteChar('\'');
310
    in.quoteChar('"');
311
 
312
    int tok;
313
    int state = STATE_BEGIN;
314
    List keystores = new LinkedList();
315
    URL currentBase = null;
316
    List currentCerts = new LinkedList();
317
    Permissions currentPerms = new Permissions();
318
    while ((tok = in.nextToken()) != StreamTokenizer.TT_EOF)
319
      {
320
        switch (tok)
321
          {
322
          case '{':
323
            if (state != STATE_GRANT)
324
              error(url, in, "spurious '{'");
325
            state = STATE_PERMS;
326
            tok = in.nextToken();
327
            break;
328
          case '}':
329
            if (state != STATE_PERMS)
330
              error(url, in, "spurious '}'");
331
            state = STATE_BEGIN;
332
            currentPerms.setReadOnly();
333
            Certificate[] c = null;
334
            if (!currentCerts.isEmpty())
335
              c = (Certificate[]) currentCerts.toArray(new Certificate[currentCerts.size()]);
336
            cs2pc.put(new CodeSource(currentBase, c), currentPerms);
337
            currentCerts.clear();
338
            currentPerms = new Permissions();
339
            currentBase = null;
340
            tok = in.nextToken();
341
            if (tok != ';')
342
              in.pushBack();
343
            continue;
344
          }
345
        if (tok != StreamTokenizer.TT_WORD)
346
          {
347
            error(url, in, "expecting word token");
348
          }
349
 
350
        // keystore "<keystore-path>" [',' "<keystore-type>"] ';'
351
        if (in.sval.equalsIgnoreCase("keystore"))
352
          {
353
            String alg = KeyStore.getDefaultType();
354
            tok = in.nextToken();
355
            if (tok != '"' && tok != '\'')
356
              error(url, in, "expecting key store URL");
357
            String store = in.sval;
358
            tok = in.nextToken();
359
            if (tok == ',')
360
              {
361
                tok = in.nextToken();
362
                if (tok != '"' && tok != '\'')
363
                  error(url, in, "expecting key store type");
364
                alg = in.sval;
365
                tok = in.nextToken();
366
              }
367
            if (tok != ';')
368
              error(url, in, "expecting semicolon");
369
            try
370
              {
371
                KeyStore keystore = KeyStore.getInstance(alg);
372
                keystore.load(new URL(url, store).openStream(), null);
373
                keystores.add(keystore);
374
              }
375
            catch (Exception x)
376
              {
377
                error(url, in, x.toString());
378
              }
379
          }
380
        else if (in.sval.equalsIgnoreCase("grant"))
381
          {
382
            if (state != STATE_BEGIN)
383
              error(url, in, "extraneous grant keyword");
384
            state = STATE_GRANT;
385
          }
386
        else if (in.sval.equalsIgnoreCase("signedBy"))
387
          {
388
            if (state != STATE_GRANT && state != STATE_PERMS)
389
              error(url, in, "spurious 'signedBy'");
390
            if (keystores.isEmpty())
391
              error(url, in, "'signedBy' with no keystores");
392
            tok = in.nextToken();
393
            if (tok != '"' && tok != '\'')
394
              error(url, in, "expecting signedBy name");
395
            StringTokenizer st = new StringTokenizer(in.sval, ",");
396
            while (st.hasMoreTokens())
397
              {
398
                String alias = st.nextToken();
399
                for (Iterator it = keystores.iterator(); it.hasNext(); )
400
                  {
401
                    KeyStore keystore = (KeyStore) it.next();
402
                    try
403
                      {
404
                        if (keystore.isCertificateEntry(alias))
405
                          currentCerts.add(keystore.getCertificate(alias));
406
                      }
407
                    catch (KeyStoreException kse)
408
                      {
409
                        error(url, in, kse.toString());
410
                      }
411
                  }
412
              }
413
            tok = in.nextToken();
414
            if (tok != ',')
415
              {
416
                if (state != STATE_GRANT)
417
                  error(url, in, "spurious ','");
418
                in.pushBack();
419
              }
420
          }
421
        else if (in.sval.equalsIgnoreCase("codeBase"))
422
          {
423
            if (state != STATE_GRANT)
424
              error(url, in, "spurious 'codeBase'");
425
            tok = in.nextToken();
426
            if (tok != '"' && tok != '\'')
427
              error(url, in, "expecting code base URL");
428
            String base = expand(in.sval);
429
            if (File.separatorChar != '/')
430
              base = base.replace(File.separatorChar, '/');
431
            try
432
              {
433
                currentBase = new URL(base);
434
              }
435
            catch (MalformedURLException mue)
436
              {
437
                error(url, in, mue.toString());
438
              }
439
            tok = in.nextToken();
440
            if (tok != ',')
441
              in.pushBack();
442
          }
443
        else if (in.sval.equalsIgnoreCase("principal"))
444
          {
445
            if (state != STATE_GRANT)
446
              error(url, in, "spurious 'principal'");
447
            tok = in.nextToken();
448
            if (tok == StreamTokenizer.TT_WORD)
449
              {
450
                tok = in.nextToken();
451
                if (tok != '"' && tok != '\'')
452
                  error(url, in, "expecting principal name");
453
                String name = in.sval;
454
                Principal p = null;
455
                try
456
                  {
457
                    Class pclass = Class.forName(in.sval);
458
                    Constructor c =
459
                      pclass.getConstructor(new Class[] { String.class });
460
                    p = (Principal) c.newInstance(new Object[] { name });
461
                  }
462
                catch (Exception x)
463
                  {
464
                    error(url, in, x.toString());
465
                  }
466
                for (Iterator it = keystores.iterator(); it.hasNext(); )
467
                  {
468
                    KeyStore ks = (KeyStore) it.next();
469
                    try
470
                      {
471
                        for (Enumeration e = ks.aliases(); e.hasMoreElements(); )
472
                          {
473
                            String alias = (String) e.nextElement();
474
                            if (ks.isCertificateEntry(alias))
475
                              {
476
                                Certificate cert = ks.getCertificate(alias);
477
                                if (!(cert instanceof X509Certificate))
478
                                  continue;
479
                                if (p.equals(((X509Certificate) cert).getSubjectDN()) ||
480
                                    p.equals(((X509Certificate) cert).getSubjectX500Principal()))
481
                                  currentCerts.add(cert);
482
                              }
483
                          }
484
                      }
485
                    catch (KeyStoreException kse)
486
                      {
487
                        error(url, in, kse.toString());
488
                      }
489
                  }
490
              }
491
            else if (tok == '"' || tok == '\'')
492
              {
493
                String alias = in.sval;
494
                for (Iterator it = keystores.iterator(); it.hasNext(); )
495
                  {
496
                    KeyStore ks = (KeyStore) it.next();
497
                    try
498
                      {
499
                        if (ks.isCertificateEntry(alias))
500
                          currentCerts.add(ks.getCertificate(alias));
501
                      }
502
                    catch (KeyStoreException kse)
503
                      {
504
                        error(url, in, kse.toString());
505
                      }
506
                  }
507
              }
508
            else
509
              error(url, in, "expecting principal");
510
            tok = in.nextToken();
511
            if (tok != ',')
512
              in.pushBack();
513
          }
514
        else if (in.sval.equalsIgnoreCase("permission"))
515
          {
516
            if (state != STATE_PERMS)
517
              error(url, in, "spurious 'permission'");
518
            tok = in.nextToken();
519
            if (tok != StreamTokenizer.TT_WORD)
520
              error(url, in, "expecting permission class name");
521
            String className = in.sval;
522
            Class clazz = null;
523
            try
524
              {
525
                clazz = Class.forName(className);
526
              }
527
            catch (ClassNotFoundException cnfe)
528
              {
529
              }
530
            tok = in.nextToken();
531
            if (tok == ';')
532
              {
533
                if (clazz == null)
534
                  {
535
                    currentPerms.add(new UnresolvedPermission(className,
536
                      null, null, (Certificate[]) currentCerts.toArray(new Certificate[currentCerts.size()])));
537
                    continue;
538
                  }
539
                try
540
                  {
541
                    currentPerms.add((Permission) clazz.newInstance());
542
                  }
543
                catch (Exception x)
544
                  {
545
                    error(url, in, x.toString());
546
                  }
547
                continue;
548
              }
549
            if (tok != '"' && tok != '\'')
550
              error(url, in, "expecting permission target");
551
            String target = expand(in.sval);
552
            tok = in.nextToken();
553
            if (tok == ';')
554
              {
555
                if (clazz == null)
556
                  {
557
                    currentPerms.add(new UnresolvedPermission(className,
558
                      target, null, (Certificate[]) currentCerts.toArray(new Certificate[currentCerts.size()])));
559
                    continue;
560
                  }
561
                try
562
                  {
563
                    Constructor c =
564
                      clazz.getConstructor(new Class[] { String.class });
565
                    currentPerms.add((Permission) c.newInstance(
566
                      new Object[] { target }));
567
                  }
568
                catch (Exception x)
569
                  {
570
                    error(url, in, x.toString());
571
                  }
572
                continue;
573
              }
574
            if (tok != ',')
575
              error(url, in, "expecting ','");
576
            tok = in.nextToken();
577
            if (tok == StreamTokenizer.TT_WORD)
578
              {
579
                if (!in.sval.equalsIgnoreCase("signedBy"))
580
                  error(url, in, "expecting 'signedBy'");
581
                try
582
                  {
583
                    Constructor c =
584
                      clazz.getConstructor(new Class[] { String.class });
585
                    currentPerms.add((Permission) c.newInstance(
586
                      new Object[] { target }));
587
                  }
588
                catch (Exception x)
589
                  {
590
                    error(url, in, x.toString());
591
                  }
592
                in.pushBack();
593
                continue;
594
              }
595
            if (tok != '"' && tok != '\'')
596
              error(url, in, "expecting permission action");
597
            String action = in.sval;
598
            if (clazz == null)
599
              {
600
                currentPerms.add(new UnresolvedPermission(className,
601
                  target, action, (Certificate[]) currentCerts.toArray(new Certificate[currentCerts.size()])));
602
                continue;
603
              }
604
            else
605
              {
606
                try
607
                  {
608
                    Constructor c = clazz.getConstructor(
609
                      new Class[] { String.class, String.class });
610
                    currentPerms.add((Permission) c.newInstance(
611
                      new Object[] { target, action }));
612
                  }
613
                catch (Exception x)
614
                  {
615
                    error(url, in, x.toString());
616
                  }
617
              }
618
            tok = in.nextToken();
619
            if (tok != ';' && tok != ',')
620
              error(url, in, "expecting ';' or ','");
621
          }
622
      }
623
  }
624
 
625
  /**
626
   * Expand all instances of <code>"${property-name}"</code> into
627
   * <code>System.getProperty("property-name")</code>.
628
   */
629
  private static String expand(final String s)
630
  {
631
    final StringBuffer result = new StringBuffer();
632
    final StringBuffer prop = new StringBuffer();
633
    int state = 0;
634
    for (int i = 0; i < s.length(); i++)
635
      {
636
        switch (state)
637
          {
638
          case 0:
639
            if (s.charAt(i) == '$')
640
              state = 1;
641
            else
642
              result.append(s.charAt(i));
643
            break;
644
          case 1:
645
            if (s.charAt(i) == '{')
646
              state = 2;
647
            else
648
              {
649
                state = 0;
650
                result.append('$').append(s.charAt(i));
651
              }
652
            break;
653
          case 2:
654
            if (s.charAt(i) == '}')
655
              {
656
                String p = prop.toString();
657
                if (p.equals("/"))
658
                  p = "file.separator";
659
                p = System.getProperty(p);
660
                if (p == null)
661
                  p = "";
662
                result.append(p);
663
                prop.setLength(0);
664
                state = 0;
665
              }
666
            else
667
              prop.append(s.charAt(i));
668
            break;
669
          }
670
      }
671
    if (state != 0)
672
      result.append('$').append('{').append(prop);
673
    return result.toString();
674
  }
675
 
676
  /**
677
   * I miss macros.
678
   */
679
  private static void error(URL base, StreamTokenizer in, String msg)
680
    throws IOException
681
  {
682
    throw new IOException(base+":"+in.lineno()+": "+msg);
683
  }
684
}

powered by: WebSVN 2.1.0

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