1 7 8 package javax.crypto; 9 10 import java.io.*; 11 import java.util.Enumeration; 12 import java.util.Hashtable; 13 import java.util.Vector; 14 import java.util.StringTokenizer; 15 16 import java.security.GeneralSecurityException; 17 import java.security.spec.AlgorithmParameterSpec; 18 import java.lang.reflect.*; 19 20 46 47 final class CryptoPolicyParser { 48 49 private Vector grantEntries; 50 51 private StreamTokenizer st; 53 private int lookahead; 54 55 58 CryptoPolicyParser() { 59 grantEntries = new Vector(); 60 } 61 62 73 74 void read(Reader policy) 75 throws ParsingException, IOException 76 { 77 if (!(policy instanceof BufferedReader)) { 78 policy = new BufferedReader(policy); 79 } 80 81 88 st = new StreamTokenizer(policy); 89 90 st.resetSyntax(); 91 st.wordChars('a', 'z'); 92 st.wordChars('A', 'Z'); 93 st.wordChars('.', '.'); 94 st.wordChars('0', '9'); 95 st.wordChars('_', '_'); 96 st.wordChars('$', '$'); 97 st.wordChars(128 + 32, 255); 98 st.whitespaceChars(0, ' '); 99 st.commentChar('/'); 100 st.quoteChar('\''); 101 st.quoteChar('"'); 102 st.lowerCaseMode(false); 103 st.ordinaryChar('/'); 104 st.slashSlashComments(true); 105 st.slashStarComments(true); 106 st.parseNumbers(); 107 108 112 Hashtable processedPermissions = null; 113 114 120 lookahead = st.nextToken(); 121 while (lookahead != StreamTokenizer.TT_EOF) { 122 if (peek("grant")) { 123 GrantEntry ge = parseGrantEntry(processedPermissions); 124 if (ge != null) 125 grantEntries.addElement(ge); 126 } else { 127 throw new ParsingException(st.lineno(), "expected grant " + 128 "statement"); 129 } 130 match(";"); 131 } 132 } 133 134 137 private GrantEntry parseGrantEntry(Hashtable processedPermissions) 138 throws ParsingException, IOException 139 { 140 GrantEntry e = new GrantEntry(); 141 142 match("grant"); 143 match("{"); 144 145 while(!peek("}")) { 146 if (peek("Permission")) { 147 CryptoPermissionEntry pe = 148 parsePermissionEntry(processedPermissions); 149 e.add(pe); 150 match(";"); 151 } else { 152 throw new 153 ParsingException(st.lineno(), "expected permission entry"); 154 } 155 } 156 match("}"); 157 158 return e; 159 } 160 161 164 private CryptoPermissionEntry parsePermissionEntry( 165 Hashtable processedPermissions) 166 throws ParsingException, IOException 167 168 { 169 CryptoPermissionEntry e = new CryptoPermissionEntry(); 170 171 match("Permission"); 172 e.cryptoPermission = match("permission type"); 173 174 if (e.cryptoPermission.equals("javax.crypto.CryptoAllPermission")) { 175 e.alg = CryptoAllPermission.ALG_NAME; 177 e.maxKeySize = Integer.MAX_VALUE; 178 return e; 179 } 180 181 if (peek("\"")) { 183 e.alg = match("quoted string").toUpperCase(); 185 } else { 186 if (peek("*")) { 188 match("*"); 189 e.alg = CryptoPermission.ALG_NAME_WILDCARD; 190 } else { 191 throw new ParsingException(st.lineno(), 192 "Missing the algorithm name"); 193 } 194 } 195 196 peekAndMatch(","); 197 198 if (peek("\"")) { 200 e.exemptionMechanism = match("quoted string").toUpperCase(); 202 } 203 204 peekAndMatch(","); 205 206 if (!isConsistent(e.alg, e.exemptionMechanism, processedPermissions)) { 209 throw new ParsingException(st.lineno(), "Inconsistent policy"); 210 } 211 212 if (peek("number")) { 214 e.maxKeySize = match(); 215 } else { 216 if (peek("*")) { 217 match("*"); 218 e.maxKeySize = Integer.MAX_VALUE; 219 } else { 220 if (!peek(";")) { 221 throw new ParsingException(st.lineno(), 222 "Missing the maximum " + 223 "allowable key size"); 224 } else { 225 e.maxKeySize = Integer.MAX_VALUE; 227 } 228 } 229 } 230 231 peekAndMatch(","); 232 233 if (peek("\"")) { 235 String algParamSpecClassName = match("quoted string"); 237 238 Vector paramsV = new Vector(1); 239 while (peek(",")) { 240 match(","); 241 if (peek("number")) { 242 paramsV.addElement(new Integer(match())); 243 } else { 244 if (peek("*")) { 245 match("*"); 246 paramsV.addElement(new Integer(Integer.MAX_VALUE)); 247 } else { 248 throw new ParsingException(st.lineno(), 249 "Expecting an integer"); 250 } 251 } 252 } 253 254 Integer[] params = new Integer[paramsV.size()]; 255 paramsV.copyInto(params); 256 257 e.checkParam = true; 258 e.algParamSpec = getInstance(algParamSpecClassName, params); 259 } 260 261 return e; 262 } 263 264 private static final AlgorithmParameterSpec getInstance(String type, 265 Integer[] params) 266 throws ParsingException 267 { 268 AlgorithmParameterSpec ret = null; 269 270 try { 271 Class apsClass = Class.forName(type); 272 Class[] paramClasses = new Class[params.length]; 273 274 for (int i = 0; i < params.length; i++) { 275 paramClasses[i] = int.class; 276 } 277 278 Constructor c = apsClass.getConstructor(paramClasses); 279 ret = (AlgorithmParameterSpec) c.newInstance(params); 280 } catch (Exception e) { 281 throw new ParsingException("Cannot call the constructor of " + 282 type + e); 283 } 284 return ret; 285 } 286 287 288 private boolean peekAndMatch(String expect) 289 throws ParsingException, IOException 290 { 291 if (peek(expect)) { 292 match(expect); 293 return true; 294 } 295 return false; 296 } 297 298 private boolean peek(String expect) { 299 boolean found = false; 300 301 switch (lookahead) { 302 303 case StreamTokenizer.TT_WORD: 304 if (expect.equalsIgnoreCase(st.sval)) 305 found = true; 306 break; 307 case StreamTokenizer.TT_NUMBER: 308 if (expect.equalsIgnoreCase("number")) { 309 found = true; 310 } 311 break; 312 case ',': 313 if (expect.equals(",")) 314 found = true; 315 break; 316 case '{': 317 if (expect.equals("{")) 318 found = true; 319 break; 320 case '}': 321 if (expect.equals("}")) 322 found = true; 323 break; 324 case '"': 325 if (expect.equals("\"")) 326 found = true; 327 break; 328 case '*': 329 if (expect.equals("*")) 330 found = true; 331 break; 332 case ';': 333 if (expect.equals(";")) 334 found = true; 335 break; 336 default: 337 break; 338 } 339 return found; 340 } 341 342 345 private int match() 346 throws ParsingException, IOException 347 { 348 int value = -1; 349 int lineno = st.lineno(); 350 String sValue = null; 351 352 switch (lookahead) { 353 case StreamTokenizer.TT_NUMBER: 354 value = (int)st.nval; 355 if (value < 0) { 356 sValue = String.valueOf(st.nval); 357 } 358 lookahead = st.nextToken(); 359 break; 360 default: 361 sValue = st.sval; 362 break; 363 } 364 if (value <= 0) { 365 throw new ParsingException(lineno, "a non-negative number", 366 sValue); 367 } 368 return value; 369 } 370 371 private String match(String expect) 372 throws ParsingException, IOException 373 { 374 String value = null; 375 376 switch (lookahead) { 377 case StreamTokenizer.TT_NUMBER: 378 throw new ParsingException(st.lineno(), expect, 379 "number "+String.valueOf(st.nval)); 380 case StreamTokenizer.TT_EOF: 381 throw new ParsingException("expected "+expect+", read end of file"); 382 case StreamTokenizer.TT_WORD: 383 if (expect.equalsIgnoreCase(st.sval)) { 384 lookahead = st.nextToken(); 385 } 386 else if (expect.equalsIgnoreCase("permission type")) { 387 value = st.sval; 388 lookahead = st.nextToken(); 389 } 390 else 391 throw new ParsingException(st.lineno(), expect, st.sval); 392 break; 393 case '"': 394 if (expect.equalsIgnoreCase("quoted string")) { 395 value = st.sval; 396 lookahead = st.nextToken(); 397 } else if (expect.equalsIgnoreCase("permission type")) { 398 value = st.sval; 399 lookahead = st.nextToken(); 400 } 401 else 402 throw new ParsingException(st.lineno(), expect, st.sval); 403 break; 404 case ',': 405 if (expect.equals(",")) 406 lookahead = st.nextToken(); 407 else 408 throw new ParsingException(st.lineno(), expect, ","); 409 break; 410 case '{': 411 if (expect.equals("{")) 412 lookahead = st.nextToken(); 413 else 414 throw new ParsingException(st.lineno(), expect, "{"); 415 break; 416 case '}': 417 if (expect.equals("}")) 418 lookahead = st.nextToken(); 419 else 420 throw new ParsingException(st.lineno(), expect, "}"); 421 break; 422 case ';': 423 if (expect.equals(";")) 424 lookahead = st.nextToken(); 425 else 426 throw new ParsingException(st.lineno(), expect, ";"); 427 break; 428 case '*': 429 if (expect.equals("*")) 430 lookahead = st.nextToken(); 431 else 432 throw new ParsingException(st.lineno(), expect, "*"); 433 break; 434 default: 435 throw new ParsingException(st.lineno(), expect, 436 new String(new char[] {(char)lookahead})); 437 } 438 return value; 439 } 440 441 CryptoPermission[] getPermissions() { 442 Vector result = new Vector(); 443 444 Enumeration grantEnum = grantEntries.elements(); 445 while (grantEnum.hasMoreElements()) { 446 GrantEntry ge = (GrantEntry)grantEnum.nextElement(); 447 Enumeration permEnum = ge.permissionElements(); 448 while (permEnum.hasMoreElements()) { 449 CryptoPermissionEntry pe = 450 (CryptoPermissionEntry)permEnum.nextElement(); 451 if (pe.cryptoPermission.equals( 452 "javax.crypto.CryptoAllPermission")) { 453 result.addElement(CryptoAllPermission.INSTANCE); 454 } else { 455 if (pe.checkParam) { 456 result.addElement(new CryptoPermission( 457 pe.alg, 458 pe.maxKeySize, 459 pe.algParamSpec, 460 pe.exemptionMechanism)); 461 } else { 462 result.addElement(new CryptoPermission( 463 pe.alg, 464 pe.maxKeySize, 465 pe.exemptionMechanism)); 466 } 467 } 468 } 469 } 470 471 CryptoPermission[] ret = new CryptoPermission[result.size()]; 472 result.copyInto(ret); 473 474 return ret; 475 } 476 477 private boolean isConsistent(String alg, 478 String exemptionMechanism, 479 Hashtable processedPermissions) { 480 String thisExemptionMechanism = 481 exemptionMechanism == null ? "none" : exemptionMechanism; 482 483 if (processedPermissions == null) { 484 processedPermissions = new Hashtable(); 485 Vector exemptionMechanisms = new Vector(1); 486 exemptionMechanisms.addElement(thisExemptionMechanism); 487 processedPermissions.put(alg, exemptionMechanisms); 488 return true; 489 } 490 491 if (processedPermissions.containsKey(CryptoAllPermission.ALG_NAME)) { 492 return false; 493 } 494 495 Vector exemptionMechanisms; 496 497 if (processedPermissions.containsKey(alg)) { 498 exemptionMechanisms = (Vector)processedPermissions.get(alg); 499 if (exemptionMechanisms.contains(thisExemptionMechanism)) { 500 return false; 501 } 502 } else { 503 exemptionMechanisms = new Vector(1); 504 } 505 506 exemptionMechanisms.addElement(thisExemptionMechanism); 507 processedPermissions.put(alg, exemptionMechanisms); 508 return true; 509 } 510 511 539 540 private static class GrantEntry { 541 542 private Vector permissionEntries; 543 544 GrantEntry() { 545 permissionEntries = new Vector(); 546 } 547 548 void add(CryptoPermissionEntry pe) 549 { 550 permissionEntries.addElement(pe); 551 } 552 553 boolean remove(CryptoPermissionEntry pe) 554 { 555 return permissionEntries.removeElement(pe); 556 } 557 558 boolean contains(CryptoPermissionEntry pe) 559 { 560 return permissionEntries.contains(pe); 561 } 562 563 566 Enumeration permissionElements(){ 567 return permissionEntries.elements(); 568 } 569 570 } 571 572 592 593 private static class CryptoPermissionEntry { 594 595 String cryptoPermission; 596 String alg; 597 String exemptionMechanism; 598 int maxKeySize; 599 boolean checkParam; 600 AlgorithmParameterSpec algParamSpec; 601 602 CryptoPermissionEntry() { 603 maxKeySize = 0; 605 alg = null; 606 exemptionMechanism = null; 607 checkParam = false; 608 algParamSpec = null; 609 } 610 611 615 public int hashCode() { 616 int retval = cryptoPermission.hashCode(); 617 if (alg != null) retval ^= alg.hashCode(); 618 if (exemptionMechanism != null) { 619 retval ^= exemptionMechanism.hashCode(); 620 } 621 retval ^= maxKeySize; 622 if (checkParam) retval ^= 100; 623 if (algParamSpec != null) { 624 retval ^= algParamSpec.hashCode(); 625 } 626 return retval; 627 } 628 629 public boolean equals(Object obj) { 630 if (obj == this) 631 return true; 632 633 if (!(obj instanceof CryptoPermissionEntry)) 634 return false; 635 636 CryptoPermissionEntry that = (CryptoPermissionEntry) obj; 637 638 if (this.cryptoPermission == null) { 639 if (that.cryptoPermission != null) return false; 640 } else { 641 if (!this.cryptoPermission.equals( 642 that.cryptoPermission)) 643 return false; 644 } 645 646 if (this.alg == null) { 647 if (that.alg != null) return false; 648 } else { 649 if (!this.alg.equalsIgnoreCase(that.alg)) 650 return false; 651 } 652 653 if (!(this.maxKeySize == that.maxKeySize)) return false; 654 655 if (this.checkParam != that.checkParam) return false; 656 657 if (this.algParamSpec == null) { 658 if (that.algParamSpec != null) return false; 659 } else { 660 if (!this.algParamSpec.equals(that.algParamSpec)) 661 return false; 662 } 663 664 return true; 666 } 667 } 668 669 static final class ParsingException extends GeneralSecurityException { 670 671 private static final long serialVersionUID = 7147241245566588374L; 672 673 678 ParsingException(String msg) { 679 super(msg); 680 } 681 682 ParsingException(int line, String msg) { 683 super("line " + line + ": " + msg); 684 } 685 686 ParsingException(int line, String expect, String actual) { 687 super("line "+line+": expected '"+expect+"', found '"+actual+"'"); 688 } 689 } 690 } 691 | Popular Tags |