1 7 8 package javax.security.auth; 9 10 import java.security.AccessController ; 11 import java.security.AccessControlContext ; 12 import java.security.AllPermission ; 13 import java.security.Permission ; 14 import java.security.Permissions ; 15 import java.security.PermissionCollection ; 16 import java.security.Policy ; 17 import java.security.Principal ; 18 import java.security.PrivilegedAction ; 19 import java.security.ProtectionDomain ; 20 import java.lang.ClassLoader ; 21 import java.security.Security ; 22 import java.util.Set ; 23 import java.util.Iterator ; 24 import java.util.WeakHashMap ; 25 import java.lang.ref.WeakReference ; 26 27 34 public class SubjectDomainCombiner implements java.security.DomainCombiner { 35 36 private Subject subject; 37 private WeakKeyValueMap<ProtectionDomain , ProtectionDomain > cachedPDs = 38 new WeakKeyValueMap<ProtectionDomain , ProtectionDomain >(); 39 private Set principalSet; 40 private Principal [] principals; 41 42 private static final sun.security.util.Debug debug = 43 sun.security.util.Debug.getInstance("combiner", 44 "\t[SubjectDomainCombiner]"); 45 46 private static final boolean useJavaxPolicy = compatPolicy(); 48 49 private static final boolean allowCaching = 51 (useJavaxPolicy && cachePolicy()); 52 53 62 public SubjectDomainCombiner(Subject subject) { 63 this.subject = subject; 64 65 if (subject.isReadOnly()) { 66 principalSet = subject.getPrincipals(); 67 principals = (Principal [])principalSet.toArray 68 (new Principal [principalSet.size()]); 69 } 70 } 71 72 87 public Subject getSubject() { 88 java.lang.SecurityManager sm = System.getSecurityManager(); 89 if (sm != null) { 90 sm.checkPermission(new AuthPermission 91 ("getSubjectFromDomainCombiner")); 92 } 93 return subject; 94 } 95 96 142 public ProtectionDomain [] combine(ProtectionDomain [] currentDomains, 143 ProtectionDomain [] assignedDomains) { 144 if (debug != null) { 145 if (subject == null) { 146 debug.println("null subject"); 147 } else { 148 final Subject s = subject; 149 AccessController.doPrivileged 150 (new java.security.PrivilegedAction () { 151 public Object run() { 152 debug.println(s.toString()); 153 return null; 154 } 155 }); 156 } 157 printInputDomains(currentDomains, assignedDomains); 158 } 159 160 if (currentDomains == null || currentDomains.length == 0) { 161 164 170 return assignedDomains; 171 } 172 173 178 currentDomains = optimize(currentDomains); 179 if (debug != null) { 180 debug.println("after optimize"); 181 printInputDomains(currentDomains, assignedDomains); 182 } 183 184 if (currentDomains == null && assignedDomains == null) { 185 return null; 186 } 187 188 if (useJavaxPolicy) { 191 return combineJavaxPolicy(currentDomains, assignedDomains); 192 } 193 194 int cLen = (currentDomains == null ? 0 : currentDomains.length); 195 int aLen = (assignedDomains == null ? 0 : assignedDomains.length); 196 197 ProtectionDomain [] newDomains = new ProtectionDomain [cLen + aLen]; 200 201 boolean allNew = true; 202 synchronized(cachedPDs) { 203 if (!subject.isReadOnly() && 204 !subject.getPrincipals().equals(principalSet)) { 205 206 Set newSet = subject.getPrincipals(); 208 synchronized(newSet) { 209 principalSet = new java.util.HashSet (newSet); 210 } 211 principals = (Principal [])principalSet.toArray 212 (new Principal [principalSet.size()]); 213 cachedPDs.clear(); 214 215 if (debug != null) { 216 debug.println("Subject mutated - clearing cache"); 217 } 218 } 219 220 ProtectionDomain subjectPd; 221 for (int i = 0; i < cLen; i++) { 222 ProtectionDomain pd = currentDomains[i]; 223 224 subjectPd = cachedPDs.getValue(pd); 225 226 if (subjectPd == null) { 227 subjectPd = new ProtectionDomain (pd.getCodeSource(), 228 pd.getPermissions(), 229 pd.getClassLoader(), 230 principals); 231 cachedPDs.putValue(pd, subjectPd); 232 } else { 233 allNew = false; 234 } 235 newDomains[i] = subjectPd; 236 } 237 } 238 239 if (debug != null) { 240 debug.println("updated current: "); 241 for (int i = 0; i < cLen; i++) { 242 debug.println("\tupdated[" + i + "] = " + 243 printDomain(newDomains[i])); 244 } 245 } 246 247 if (aLen > 0) { 249 System.arraycopy(assignedDomains, 0, newDomains, cLen, aLen); 250 251 if (!allNew) { 253 newDomains = optimize(newDomains); 254 } 255 } 256 257 259 if (debug != null) { 260 if (newDomains == null || newDomains.length == 0) { 261 debug.println("returning null"); 262 } else { 263 debug.println("combinedDomains: "); 264 for (int i = 0; i < newDomains.length; i++) { 265 debug.println("newDomain " + i + ": " + 266 printDomain(newDomains[i])); 267 } 268 } 269 } 270 271 if (newDomains == null || newDomains.length == 0) { 273 return null; 274 } else { 275 return newDomains; 276 } 277 } 278 279 282 private ProtectionDomain [] combineJavaxPolicy( 283 ProtectionDomain [] currentDomains, 284 ProtectionDomain [] assignedDomains) { 285 286 if (!allowCaching) { 287 java.security.AccessController.doPrivileged 288 (new PrivilegedAction () { 289 public Object run() { 290 javax.security.auth.Policy.getPolicy().refresh(); 292 return null; 293 } 294 }); 295 } 296 297 int cLen = (currentDomains == null ? 0 : currentDomains.length); 298 int aLen = (assignedDomains == null ? 0 : assignedDomains.length); 299 300 ProtectionDomain [] newDomains = new ProtectionDomain [cLen + aLen]; 303 304 synchronized(cachedPDs) { 305 if (!subject.isReadOnly() && 306 !subject.getPrincipals().equals(principalSet)) { 307 308 Set newSet = subject.getPrincipals(); 310 synchronized(newSet) { 311 principalSet = new java.util.HashSet (newSet); 312 } 313 principals = (Principal [])principalSet.toArray 314 (new Principal [principalSet.size()]); 315 cachedPDs.clear(); 316 317 if (debug != null) { 318 debug.println("Subject mutated - clearing cache"); 319 } 320 } 321 322 for (int i = 0; i < cLen; i++) { 323 ProtectionDomain pd = currentDomains[i]; 324 ProtectionDomain subjectPd = cachedPDs.getValue(pd); 325 326 if (subjectPd == null) { 327 328 334 Permissions perms = new Permissions (); 336 PermissionCollection coll = pd.getPermissions(); 337 java.util.Enumeration e; 338 if (coll != null) { 339 synchronized (coll) { 340 e = coll.elements(); 341 while (e.hasMoreElements()) { 342 Permission newPerm = 343 (Permission )e.nextElement(); 344 perms.add(newPerm); 345 } 346 } 347 } 348 349 351 final java.security.CodeSource finalCs = pd.getCodeSource(); 352 final Subject finalS = subject; 353 PermissionCollection newPerms = (PermissionCollection ) 354 java.security.AccessController.doPrivileged 355 (new PrivilegedAction () { 356 public Object run() { 357 return 358 javax.security.auth.Policy.getPolicy().getPermissions 359 (finalS, finalCs); 360 } 361 }); 362 363 synchronized (newPerms) { 366 e = newPerms.elements(); 367 while (e.hasMoreElements()) { 368 Permission newPerm = (Permission )e.nextElement(); 369 if (!perms.implies(newPerm)) { 370 perms.add(newPerm); 371 if (debug != null) 372 debug.println ( 373 "Adding perm " + newPerm + "\n"); 374 } 375 } 376 } 377 subjectPd = new ProtectionDomain 378 (finalCs, perms, pd.getClassLoader(), principals); 379 380 if (allowCaching) 381 cachedPDs.putValue(pd, subjectPd); 382 } 383 newDomains[i] = subjectPd; 384 } 385 } 386 387 if (debug != null) { 388 debug.println("updated current: "); 389 for (int i = 0; i < cLen; i++) { 390 debug.println("\tupdated[" + i + "] = " + newDomains[i]); 391 } 392 } 393 394 if (aLen > 0) { 396 System.arraycopy(assignedDomains, 0, newDomains, cLen, aLen); 397 } 398 399 if (debug != null) { 400 if (newDomains == null || newDomains.length == 0) { 401 debug.println("returning null"); 402 } else { 403 debug.println("combinedDomains: "); 404 for (int i = 0; i < newDomains.length; i++) { 405 debug.println("newDomain " + i + ": " + 406 newDomains[i].toString()); 407 } 408 } 409 } 410 411 if (newDomains == null || newDomains.length == 0) { 413 return null; 414 } else { 415 return newDomains; 416 } 417 } 418 419 private static ProtectionDomain [] optimize(ProtectionDomain [] domains) { 420 if (domains == null || domains.length == 0) 421 return null; 422 423 ProtectionDomain [] optimized = new ProtectionDomain [domains.length]; 424 ProtectionDomain pd; 425 int num = 0; 426 for (int i = 0; i < domains.length; i++) { 427 428 434 if ((pd = domains[i]) != null) { 436 437 boolean found = false; 439 for (int j = 0; j < num && !found; j++) { 440 found = (optimized[j] == pd); 441 } 442 if (!found) { 443 optimized[num++] = pd; 444 } 445 } 446 } 447 448 if (num > 0 && num < domains.length) { 450 ProtectionDomain [] downSize = new ProtectionDomain [num]; 451 System.arraycopy(optimized, 0, downSize, 0, downSize.length); 452 optimized = downSize; 453 } 454 455 return ((num == 0 || optimized.length == 0) ? null : optimized); 456 } 457 458 private static boolean cachePolicy() { 459 String s = (String )AccessController.doPrivileged 460 (new PrivilegedAction () { 461 public Object run() { 462 return java.security.Security.getProperty 463 ("cache.auth.policy"); 464 } 465 }); 466 if (s != null) { 467 Boolean b = new Boolean (s); 468 return b.booleanValue(); 469 } 470 471 return true; 473 } 474 475 private static boolean compatPolicy() { 478 javax.security.auth.Policy javaxPolicy = 479 (javax.security.auth.Policy )AccessController.doPrivileged 480 (new PrivilegedAction () { 481 public Object run() { 482 return javax.security.auth.Policy.getPolicy(); 483 } 484 }); 485 486 if (!(javaxPolicy instanceof com.sun.security.auth.PolicyFile)) { 487 if (debug != null) { 488 debug.println("Providing backwards compatibility for " + 489 "javax.security.auth.policy implementation: " + 490 javaxPolicy.toString()); 491 } 492 493 return true; 494 } else { 495 return false; 496 } 497 } 498 499 private static void printInputDomains(ProtectionDomain [] currentDomains, 500 ProtectionDomain [] assignedDomains) { 501 if (currentDomains == null || currentDomains.length == 0) { 502 debug.println("currentDomains null or 0 length"); 503 } else { 504 for (int i = 0; currentDomains != null && 505 i < currentDomains.length; i++) { 506 if (currentDomains[i] == null) { 507 debug.println("currentDomain " + i + ": SystemDomain"); 508 } else { 509 debug.println("currentDomain " + i + ": " + 510 printDomain(currentDomains[i])); 511 } 512 } 513 } 514 515 if (assignedDomains == null || assignedDomains.length == 0) { 516 debug.println("assignedDomains null or 0 length"); 517 } else { 518 debug.println("assignedDomains = "); 519 for (int i = 0; assignedDomains != null && 520 i < assignedDomains.length; i++) { 521 if (assignedDomains[i] == null) { 522 debug.println("assignedDomain " + i + ": SystemDomain"); 523 } else { 524 debug.println("assignedDomain " + i + ": " + 525 printDomain(assignedDomains[i])); 526 } 527 } 528 } 529 } 530 531 private static String printDomain(final ProtectionDomain pd) { 532 if (pd == null) { 533 return "null"; 534 } 535 return (String )AccessController.doPrivileged(new PrivilegedAction () { 536 public Object run() { 537 return pd.toString(); 538 } 539 }); 540 } 541 542 558 private static class WeakKeyValueMap<K,V> extends 559 WeakHashMap <K,WeakReference <V>> { 560 561 public V getValue(K key) { 562 WeakReference <V> wr = super.get(key); 563 if (wr != null) { 564 return wr.get(); 565 } 566 return null; 567 } 568 569 public V putValue(K key, V value) { 570 WeakReference <V> wr = super.put(key, new WeakReference <V>(value)); 571 if (wr != null) { 572 return wr.get(); 573 } 574 return null; 575 } 576 } 577 } 578 | Popular Tags |