1 /*
2 * Copyright (c) 1998, 2006, 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 com.sun.security.auth;
27
28 import java.io.*;
29 import java.lang.RuntimePermission;
30 import java.net.MalformedURLException;
31 import java.net.SocketPermission;
32 import java.net.URL;
33 import java.util.Enumeration;
34 import java.util.Hashtable;
35 import java.util.LinkedList;
36 import java.util.ListIterator;
37 import java.util.Vector;
38 import java.util.StringTokenizer;
39 import java.security.GeneralSecurityException;
40 import sun.security.util.PropertyExpander;
41
42 /**
43 * The policy for a Java runtime (specifying
44 * which permissions are available for code from various principals)
45 * is represented as a separate
46 * persistent configuration. The configuration may be stored as a
47 * flat ASCII file, as a serialized binary file of
48 * the Policy class, or as a database. <p>
49 *
50 * <p>The Java runtime creates one global Policy object, which is used to
51 * represent the static policy configuration file. It is consulted by
52 * a ProtectionDomain when the protection domain initializes its set of
53 * permissions. <p>
54 *
55 * <p>The Policy <code>init</code> method parses the policy
56 * configuration file, and then
57 * populates the Policy object. The Policy object is agnostic in that
58 * it is not involved in making policy decisions. It is merely the
59 * Java runtime representation of the persistent policy configuration
283 out.flush();
284 }
285
286 /**
287 * parses a keystore entry
288 */
289 private void parseKeyStoreEntry() throws ParsingException, IOException {
290 match("keystore");
291 keyStoreUrlString = match("quoted string");
292
293 // parse keystore type
294 if (!peek(",")) {
295 return; // default type
296 }
297 match(",");
298
299 if (peek("\"")) {
300 keyStoreType = match("quoted string");
301 } else {
302 throw new ParsingException(st.lineno(),
303 rb.getString("expected keystore type"));
304 }
305 }
306
307 /**
308 * writes the (unexpanded) keystore entry
309 */
310 private void writeKeyStoreEntry(PrintWriter out) {
311 out.print("keystore \"");
312 out.print(keyStoreUrlString);
313 out.print('"');
314 if (keyStoreType != null && keyStoreType.length() > 0)
315 out.print(", \"" + keyStoreType + "\"");
316 out.println(";");
317 out.println();
318 }
319
320 /**
321 * parse a Grant entry
322 */
323 private GrantEntry parseGrantEntry()
351 principalClass = match("principal type");
352 }
353
354 // check for principalName wildcard
355 String principalName;
356 if (peek("*")) {
357 match("*");
358 principalName = PrincipalEntry.WILDCARD_NAME;
359 } else {
360 principalName = match("quoted string");
361 }
362
363 // disallow WILDCARD_CLASS && actual name
364 if (principalClass.equals(PrincipalEntry.WILDCARD_CLASS) &&
365 !principalName.equals(PrincipalEntry.WILDCARD_NAME)) {
366 if (debug != null)
367 debug.println("disallowing principal that has " +
368 "WILDCARD class but no WILDCARD name");
369 throw new ParsingException
370 (st.lineno(),
371 rb.getString("can not specify Principal with a ") +
372 rb.getString("wildcard class without a wildcard name"));
373 }
374
375 try {
376 principalName = expand(principalName);
377 principals.add
378 (new PrincipalEntry(principalClass, principalName));
379 } catch (PropertyExpander.ExpandException peee) {
380 // ignore the entire policy entry
381 // but continue parsing all the info
382 // so we can get to the next entry
383 if (debug != null)
384 debug.println("principal name expansion failed: " +
385 principalName);
386 ignoreEntry = true;
387 }
388 peekAndMatch(",");
389 } else {
390 throw new
391 ParsingException(st.lineno(),
392 rb.getString("expected codeBase or SignedBy"));
393 }
394 }
395
396 // disallow non principal-based grant entries
397 if (principals == null) {
398 throw new ParsingException
399 (st.lineno(),
400 rb.getString("only Principal-based grant entries permitted"));
401 }
402
403 e.principals = principals;
404 match("{");
405
406 while(!peek("}")) {
407 if (peek("Permission")) {
408 try {
409 PermissionEntry pe = parsePermissionEntry();
410 e.add(pe);
411 } catch (PropertyExpander.ExpandException peee) {
412 // ignore. The add never happened
413 skipEntry(); // BugId 4219343
414 }
415 match(";");
416 } else {
417 throw new
418 ParsingException(st.lineno(),
419 rb.getString("expected permission entry"));
420 }
421 }
422 match("}");
423
424 try {
425 if (e.codeBase != null)
426 e.codeBase = expand(e.codeBase).replace(File.separatorChar, '/');
427 e.signedBy = expand(e.signedBy);
428 } catch (PropertyExpander.ExpandException peee) {
429 return null;
430 }
431
432 return (ignoreEntry == true) ? null : e;
433 }
434
435 /**
436 * parse a Permission entry
437 */
438 private PermissionEntry parsePermissionEntry()
439 throws ParsingException, IOException, PropertyExpander.ExpandException
505 found = true;
506 break;
507 case '*':
508 if (expect.equalsIgnoreCase("*"))
509 found = true;
510 break;
511 default:
512
513 }
514 return found;
515 }
516
517 private String match(String expect)
518 throws ParsingException, IOException
519 {
520 String value = null;
521
522 switch (lookahead) {
523 case StreamTokenizer.TT_NUMBER:
524 throw new ParsingException(st.lineno(), expect,
525 rb.getString("number ") +
526 String.valueOf(st.nval));
527 case StreamTokenizer.TT_EOF:
528 throw new ParsingException
529 (rb.getString("expected ") + expect +
530 rb.getString(", read end of file"));
531 case StreamTokenizer.TT_WORD:
532 if (expect.equalsIgnoreCase(st.sval)) {
533 lookahead = st.nextToken();
534 } else if (expect.equalsIgnoreCase("permission type")) {
535 value = st.sval;
536 lookahead = st.nextToken();
537 } else if (expect.equalsIgnoreCase("principal type")) {
538 value = st.sval;
539 lookahead = st.nextToken();
540 } else {
541 throw new ParsingException(st.lineno(), expect, st.sval);
542 }
543 break;
544 case '"':
545 if (expect.equalsIgnoreCase("quoted string")) {
546 value = st.sval;
547 lookahead = st.nextToken();
548 } else if (expect.equalsIgnoreCase("permission type")) {
549 value = st.sval;
550 lookahead = st.nextToken();
586 throw new ParsingException(st.lineno(), expect, "*");
587 break;
588 default:
589 throw new ParsingException(st.lineno(), expect,
590 new String(new char[] {(char)lookahead}));
591 }
592 return value;
593 }
594
595 /**
596 * skip all tokens for this entry leaving the delimiter ";"
597 * in the stream.
598 */
599 private void skipEntry()
600 throws ParsingException, IOException
601 {
602 while(lookahead != ';') {
603 switch (lookahead) {
604 case StreamTokenizer.TT_NUMBER:
605 throw new ParsingException(st.lineno(), ";",
606 rb.getString("number ") +
607 String.valueOf(st.nval));
608 case StreamTokenizer.TT_EOF:
609 throw new ParsingException
610 (rb.getString("expected ';', read end of file"));
611 default:
612 lookahead = st.nextToken();
613 }
614 }
615 }
616
617 /**
618 * Each grant entry in the policy configuration file is
619 * represented by a
620 * GrantEntry object. <p>
621 *
622 * <p>
623 * For example, the entry
624 * <pre>
625 * grant signedBy "Duke" {
626 * permission java.io.FilePermission "/tmp", "read,write";
627 * };
628 *
629 * </pre>
630 * is represented internally
925 }
926 }
927
928 static class ParsingException extends GeneralSecurityException {
929
930 private static final long serialVersionUID = 8240970523155877400L;
931
932 /**
933 * Constructs a ParsingException with the specified
934 * detail message. A detail message is a String that describes
935 * this particular exception, which may, for example, specify which
936 * algorithm is not available.
937 *
938 * @param msg the detail message.
939 */
940 public ParsingException(String msg) {
941 super(msg);
942 }
943
944 public ParsingException(int line, String msg) {
945 super(rb.getString("line ") + line + rb.getString(": ") + msg);
946 }
947
948 public ParsingException(int line, String expect, String actual) {
949 super(rb.getString("line ") + line + rb.getString(": expected '") +
950 expect + rb.getString("', found '") + actual +
951 rb.getString("'"));
952 }
953 }
954
955 public static void main(String arg[]) throws Exception {
956 PolicyParser pp = new PolicyParser(true);
957 pp.read(new FileReader(arg[0]));
958 FileWriter fr = new FileWriter(arg[1]);
959 pp.write(fr);
960 fr.close();
961 }
962 }
|
1 /*
2 * Copyright (c) 1998, 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 com.sun.security.auth;
27
28 import java.io.*;
29 import java.lang.RuntimePermission;
30 import java.net.MalformedURLException;
31 import java.net.SocketPermission;
32 import java.net.URL;
33 import java.security.GeneralSecurityException;
34 import java.text.MessageFormat;
35 import java.util.Enumeration;
36 import java.util.Hashtable;
37 import java.util.LinkedList;
38 import java.util.ListIterator;
39 import java.util.Vector;
40 import java.util.StringTokenizer;
41 import sun.security.util.PropertyExpander;
42
43 /**
44 * The policy for a Java runtime (specifying
45 * which permissions are available for code from various principals)
46 * is represented as a separate
47 * persistent configuration. The configuration may be stored as a
48 * flat ASCII file, as a serialized binary file of
49 * the Policy class, or as a database. <p>
50 *
51 * <p>The Java runtime creates one global Policy object, which is used to
52 * represent the static policy configuration file. It is consulted by
53 * a ProtectionDomain when the protection domain initializes its set of
54 * permissions. <p>
55 *
56 * <p>The Policy <code>init</code> method parses the policy
57 * configuration file, and then
58 * populates the Policy object. The Policy object is agnostic in that
59 * it is not involved in making policy decisions. It is merely the
60 * Java runtime representation of the persistent policy configuration
284 out.flush();
285 }
286
287 /**
288 * parses a keystore entry
289 */
290 private void parseKeyStoreEntry() throws ParsingException, IOException {
291 match("keystore");
292 keyStoreUrlString = match("quoted string");
293
294 // parse keystore type
295 if (!peek(",")) {
296 return; // default type
297 }
298 match(",");
299
300 if (peek("\"")) {
301 keyStoreType = match("quoted string");
302 } else {
303 throw new ParsingException(st.lineno(),
304 rb.getString("expected.keystore.type"));
305 }
306 }
307
308 /**
309 * writes the (unexpanded) keystore entry
310 */
311 private void writeKeyStoreEntry(PrintWriter out) {
312 out.print("keystore \"");
313 out.print(keyStoreUrlString);
314 out.print('"');
315 if (keyStoreType != null && keyStoreType.length() > 0)
316 out.print(", \"" + keyStoreType + "\"");
317 out.println(";");
318 out.println();
319 }
320
321 /**
322 * parse a Grant entry
323 */
324 private GrantEntry parseGrantEntry()
352 principalClass = match("principal type");
353 }
354
355 // check for principalName wildcard
356 String principalName;
357 if (peek("*")) {
358 match("*");
359 principalName = PrincipalEntry.WILDCARD_NAME;
360 } else {
361 principalName = match("quoted string");
362 }
363
364 // disallow WILDCARD_CLASS && actual name
365 if (principalClass.equals(PrincipalEntry.WILDCARD_CLASS) &&
366 !principalName.equals(PrincipalEntry.WILDCARD_NAME)) {
367 if (debug != null)
368 debug.println("disallowing principal that has " +
369 "WILDCARD class but no WILDCARD name");
370 throw new ParsingException
371 (st.lineno(),
372 rb.getString("can.not.specify.Principal.with.a." +
373 "wildcard.class.without.a.wildcard.name"));
374 }
375
376 try {
377 principalName = expand(principalName);
378 principals.add
379 (new PrincipalEntry(principalClass, principalName));
380 } catch (PropertyExpander.ExpandException peee) {
381 // ignore the entire policy entry
382 // but continue parsing all the info
383 // so we can get to the next entry
384 if (debug != null)
385 debug.println("principal name expansion failed: " +
386 principalName);
387 ignoreEntry = true;
388 }
389 peekAndMatch(",");
390 } else {
391 throw new
392 ParsingException(st.lineno(),
393 rb.getString("expected.codeBase.or.SignedBy"));
394 }
395 }
396
397 // disallow non principal-based grant entries
398 if (principals == null) {
399 throw new ParsingException
400 (st.lineno(),
401 rb.getString("only.Principal.based.grant.entries.permitted"));
402 }
403
404 e.principals = principals;
405 match("{");
406
407 while(!peek("}")) {
408 if (peek("Permission")) {
409 try {
410 PermissionEntry pe = parsePermissionEntry();
411 e.add(pe);
412 } catch (PropertyExpander.ExpandException peee) {
413 // ignore. The add never happened
414 skipEntry(); // BugId 4219343
415 }
416 match(";");
417 } else {
418 throw new
419 ParsingException(st.lineno(),
420 rb.getString("expected.permission.entry"));
421 }
422 }
423 match("}");
424
425 try {
426 if (e.codeBase != null)
427 e.codeBase = expand(e.codeBase).replace(File.separatorChar, '/');
428 e.signedBy = expand(e.signedBy);
429 } catch (PropertyExpander.ExpandException peee) {
430 return null;
431 }
432
433 return (ignoreEntry == true) ? null : e;
434 }
435
436 /**
437 * parse a Permission entry
438 */
439 private PermissionEntry parsePermissionEntry()
440 throws ParsingException, IOException, PropertyExpander.ExpandException
506 found = true;
507 break;
508 case '*':
509 if (expect.equalsIgnoreCase("*"))
510 found = true;
511 break;
512 default:
513
514 }
515 return found;
516 }
517
518 private String match(String expect)
519 throws ParsingException, IOException
520 {
521 String value = null;
522
523 switch (lookahead) {
524 case StreamTokenizer.TT_NUMBER:
525 throw new ParsingException(st.lineno(), expect,
526 rb.getString("number.") +
527 String.valueOf(st.nval));
528 case StreamTokenizer.TT_EOF:
529 MessageFormat form = new MessageFormat(
530 rb.getString("expected.expect.read.end.of.file."));
531 Object[] source = {expect};
532 throw new ParsingException(form.format(source));
533 case StreamTokenizer.TT_WORD:
534 if (expect.equalsIgnoreCase(st.sval)) {
535 lookahead = st.nextToken();
536 } else if (expect.equalsIgnoreCase("permission type")) {
537 value = st.sval;
538 lookahead = st.nextToken();
539 } else if (expect.equalsIgnoreCase("principal type")) {
540 value = st.sval;
541 lookahead = st.nextToken();
542 } else {
543 throw new ParsingException(st.lineno(), expect, st.sval);
544 }
545 break;
546 case '"':
547 if (expect.equalsIgnoreCase("quoted string")) {
548 value = st.sval;
549 lookahead = st.nextToken();
550 } else if (expect.equalsIgnoreCase("permission type")) {
551 value = st.sval;
552 lookahead = st.nextToken();
588 throw new ParsingException(st.lineno(), expect, "*");
589 break;
590 default:
591 throw new ParsingException(st.lineno(), expect,
592 new String(new char[] {(char)lookahead}));
593 }
594 return value;
595 }
596
597 /**
598 * skip all tokens for this entry leaving the delimiter ";"
599 * in the stream.
600 */
601 private void skipEntry()
602 throws ParsingException, IOException
603 {
604 while(lookahead != ';') {
605 switch (lookahead) {
606 case StreamTokenizer.TT_NUMBER:
607 throw new ParsingException(st.lineno(), ";",
608 rb.getString("number.") +
609 String.valueOf(st.nval));
610 case StreamTokenizer.TT_EOF:
611 throw new ParsingException
612 (rb.getString("expected.read.end.of.file"));
613 default:
614 lookahead = st.nextToken();
615 }
616 }
617 }
618
619 /**
620 * Each grant entry in the policy configuration file is
621 * represented by a
622 * GrantEntry object. <p>
623 *
624 * <p>
625 * For example, the entry
626 * <pre>
627 * grant signedBy "Duke" {
628 * permission java.io.FilePermission "/tmp", "read,write";
629 * };
630 *
631 * </pre>
632 * is represented internally
927 }
928 }
929
930 static class ParsingException extends GeneralSecurityException {
931
932 private static final long serialVersionUID = 8240970523155877400L;
933
934 /**
935 * Constructs a ParsingException with the specified
936 * detail message. A detail message is a String that describes
937 * this particular exception, which may, for example, specify which
938 * algorithm is not available.
939 *
940 * @param msg the detail message.
941 */
942 public ParsingException(String msg) {
943 super(msg);
944 }
945
946 public ParsingException(int line, String msg) {
947 super(rb.getString("line.") + line + rb.getString("COLON") + msg);
948 }
949
950 public ParsingException(int line, String expect, String actual) {
951 super(rb.getString("line.") + line + rb.getString(".expected.") +
952 expect + rb.getString(".found.") + actual +
953 rb.getString("QUOTE"));
954 }
955 }
956
957 public static void main(String arg[]) throws Exception {
958 PolicyParser pp = new PolicyParser(true);
959 pp.read(new FileReader(arg[0]));
960 FileWriter fr = new FileWriter(arg[1]);
961 pp.write(fr);
962 fr.close();
963 }
964 }
|