< prev index next >

src/share/classes/com/sun/security/auth/PolicyParser.java

Print this page
rev 1461 : 6987827: security/util/Resources.java needs improvement
Reviewed-by: valeriep
rev 1466 : 7019937: Translatability bug - Remove Unused String - String ID , read end of file
7019938: Translatability bug - Remove Unused String - String ID can not specify Principal with a
7019940: Translatability bug - Remove unused string - String ID: provided null name
7019942: Translatability bug - String ID: trustedCertEntry,
7019945: Translatability bug - Translatability issue - String ID: * has NOT been verified! In order to veri
7019947: Translatability bug - Translatability issue - String ID: * The integrity of the information stored i
7019949: Translatability bug - Translatability issue - String ID: * you must provide your keystore password.
Reviewed-by: weijun, wetmore
   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 }
< prev index next >