1 /* 2 * Copyright (c) 1999, 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.net.URL; 29 import java.util.*; 30 import java.security.CodeSource; 31 import java.security.Principal; 32 import java.security.cert.Certificate; 33 import java.lang.reflect.Constructor; 34 35 import javax.security.auth.Subject; 36 37 /** 38 * <p> This <code>SubjectCodeSource</code> class contains 39 * a <code>URL</code>, signer certificates, and either a <code>Subject</code> 40 * (that represents the <code>Subject</code> in the current 41 * <code>AccessControlContext</code>), 42 * or a linked list of Principals/PrincipalComparators 43 * (that represent a "subject" in a <code>Policy</code>). 44 * 45 */ 46 class SubjectCodeSource extends CodeSource implements java.io.Serializable { 47 48 private static final long serialVersionUID = 6039418085604715275L; 49 50 private static final java.util.ResourceBundle rb = 51 java.security.AccessController.doPrivileged 52 (new java.security.PrivilegedAction<java.util.ResourceBundle>() { 53 public java.util.ResourceBundle run() { 54 return (java.util.ResourceBundle.getBundle 55 ("sun.security.util.AuthResources")); 56 } 57 }); 58 59 private Subject subject; 60 private LinkedList<PolicyParser.PrincipalEntry> principals; 61 private static final Class[] PARAMS = { String.class }; 62 private static final sun.security.util.Debug debug = 63 sun.security.util.Debug.getInstance("auth", "\t[Auth Access]"); 64 private ClassLoader sysClassLoader; 65 66 /** 67 * Creates a new <code>SubjectCodeSource</code> 68 * with the given <code>Subject</code>, principals, <code>URL</code>, 69 * and signers (Certificates). The <code>Subject</code> 70 * represents the <code>Subject</code> associated with the current 71 * <code>AccessControlContext</code>. 72 * The Principals are given as a <code>LinkedList</code> 73 * of <code>PolicyParser.PrincipalEntry</code> objects. 74 * Typically either a <code>Subject</code> will be provided, 75 * or a list of <code>principals</code> will be provided 76 * (not both). 77 * 78 * <p> 79 * 80 * @param subject the <code>Subject</code> associated with this 81 * <code>SubjectCodeSource</code> <p> 82 * 83 * @param url the <code>URL</code> associated with this 84 * <code>SubjectCodeSource</code> <p> 85 * 86 * @param certs the signers associated with this 87 * <code>SubjectCodeSource</code> <p> 88 */ 89 SubjectCodeSource(Subject subject, 90 LinkedList<PolicyParser.PrincipalEntry> principals, 91 URL url, Certificate[] certs) { 92 93 super(url, certs); 94 this.subject = subject; 95 this.principals = (principals == null ? 96 new LinkedList<PolicyParser.PrincipalEntry>() : 97 new LinkedList<PolicyParser.PrincipalEntry>(principals)); 98 sysClassLoader = java.security.AccessController.doPrivileged 99 (new java.security.PrivilegedAction<ClassLoader>() { 100 public ClassLoader run() { 101 return ClassLoader.getSystemClassLoader(); 102 } 103 }); 104 } 105 106 /** 107 * Get the Principals associated with this <code>SubjectCodeSource</code>. 108 * The Principals are retrieved as a <code>LinkedList</code> 109 * of <code>PolicyParser.PrincipalEntry</code> objects. 110 * 111 * <p> 112 * 113 * @return the Principals associated with this 114 * <code>SubjectCodeSource</code> as a <code>LinkedList</code> 115 * of <code>PolicyParser.PrincipalEntry</code> objects. 116 */ 117 LinkedList<PolicyParser.PrincipalEntry> getPrincipals() { 118 return principals; 119 } 120 121 /** 122 * Get the <code>Subject</code> associated with this 123 * <code>SubjectCodeSource</code>. The <code>Subject</code> 124 * represents the <code>Subject</code> associated with the 125 * current <code>AccessControlContext</code>. 126 * 127 * <p> 128 * 129 * @return the <code>Subject</code> associated with this 130 * <code>SubjectCodeSource</code>. 131 */ 132 Subject getSubject() { 133 return subject; 134 } 135 136 /** 137 * Returns true if this <code>SubjectCodeSource</code> object "implies" 138 * the specified <code>CodeSource</code>. 139 * More specifically, this method makes the following checks. 140 * If any fail, it returns false. If they all succeed, it returns true. 141 * 142 * <p> 143 * <ol> 144 * <li> The provided codesource must not be <code>null</code>. 145 * <li> codesource must be an instance of <code>SubjectCodeSource</code>. 146 * <li> super.implies(codesource) must return true. 147 * <li> for each principal in this codesource's principal list: 148 * <ol> 149 * <li> if the principal is an instanceof 150 * <code>PrincipalComparator</code>, then the principal must 151 * imply the provided codesource's <code>Subject</code>. 152 * <li> if the principal is not an instanceof 153 * <code>PrincipalComparator</code>, then the provided 154 * codesource's <code>Subject</code> must have an 155 * associated <code>Principal</code>, <i>P</i>, where 156 * P.getClass().getName equals principal.principalClass, 157 * and P.getName() equals principal.principalName. 158 * </ol> 159 * </ol> 160 * 161 * <p> 162 * 163 * @param codesource the <code>CodeSource</code> to compare against. 164 * 165 * @return true if this <code>SubjectCodeSource</code> implies the 166 * the specified <code>CodeSource</code>. 167 */ 168 public boolean implies(CodeSource codesource) { 169 170 LinkedList<PolicyParser.PrincipalEntry> subjectList = null; 171 172 if (codesource == null || 173 !(codesource instanceof SubjectCodeSource) || 174 !(super.implies(codesource))) { 175 176 if (debug != null) 177 debug.println("\tSubjectCodeSource.implies: FAILURE 1"); 178 return false; 179 } 180 181 SubjectCodeSource that = (SubjectCodeSource)codesource; 182 183 // if the principal list in the policy "implies" 184 // the Subject associated with the current AccessControlContext, 185 // then return true 186 187 if (this.principals == null) { 188 if (debug != null) 189 debug.println("\tSubjectCodeSource.implies: PASS 1"); 190 return true; 191 } 192 193 if (that.getSubject() == null || 194 that.getSubject().getPrincipals().size() == 0) { 195 if (debug != null) 196 debug.println("\tSubjectCodeSource.implies: FAILURE 2"); 197 return false; 198 } 199 200 ListIterator<PolicyParser.PrincipalEntry> li = 201 this.principals.listIterator(0); 202 while (li.hasNext()) { 203 PolicyParser.PrincipalEntry pppe = li.next(); 204 try { 205 206 // handle PrincipalComparators 207 208 Class<?> principalComparator = Class.forName( 209 pppe.principalClass, true, sysClassLoader); 210 Constructor<?> c = principalComparator.getConstructor(PARAMS); 211 PrincipalComparator pc = 212 (PrincipalComparator)c.newInstance 213 (new Object[] { pppe.principalName }); 214 215 if (!pc.implies(that.getSubject())) { 216 if (debug != null) 217 debug.println("\tSubjectCodeSource.implies: FAILURE 3"); 218 return false; 219 } else { 220 if (debug != null) 221 debug.println("\tSubjectCodeSource.implies: PASS 2"); 222 return true; 223 } 224 } catch (Exception e) { 225 226 // no PrincipalComparator, simply compare Principals 227 228 if (subjectList == null) { 229 230 if (that.getSubject() == null) { 231 if (debug != null) 232 debug.println("\tSubjectCodeSource.implies: " + 233 "FAILURE 4"); 234 return false; 235 } 236 Iterator<Principal> i = 237 that.getSubject().getPrincipals().iterator(); 238 239 subjectList = new LinkedList<PolicyParser.PrincipalEntry>(); 240 while (i.hasNext()) { 241 Principal p = i.next(); 242 PolicyParser.PrincipalEntry spppe = 243 new PolicyParser.PrincipalEntry 244 (p.getClass().getName(), p.getName()); 245 subjectList.add(spppe); 246 } 247 } 248 249 if (!subjectListImpliesPrincipalEntry(subjectList, pppe)) { 250 if (debug != null) 251 debug.println("\tSubjectCodeSource.implies: FAILURE 5"); 252 return false; 253 } 254 } 255 } 256 257 if (debug != null) 258 debug.println("\tSubjectCodeSource.implies: PASS 3"); 259 return true; 260 } 261 262 /** 263 * This method returns, true, if the provided <i>subjectList</i> 264 * "contains" the <code>Principal</code> specified 265 * in the provided <i>pppe</i> argument. 266 * 267 * Note that the provided <i>pppe</i> argument may have 268 * wildcards (*) for the <code>Principal</code> class and name, 269 * which need to be considered. 270 * 271 * <p> 272 * 273 * @param subjectList a list of PolicyParser.PrincipalEntry objects 274 * that correspond to all the Principals in the Subject currently 275 * on this thread's AccessControlContext. <p> 276 * 277 * @param pppe the Principals specified in a grant entry. 278 * 279 * @return true if the provided <i>subjectList</i> "contains" 280 * the <code>Principal</code> specified in the provided 281 * <i>pppe</i> argument. 282 */ 283 private boolean subjectListImpliesPrincipalEntry( 284 LinkedList<PolicyParser.PrincipalEntry> subjectList, 285 PolicyParser.PrincipalEntry pppe) { 286 287 ListIterator<PolicyParser.PrincipalEntry> li = 288 subjectList.listIterator(0); 289 while (li.hasNext()) { 290 PolicyParser.PrincipalEntry listPppe = li.next(); 291 292 if (pppe.principalClass.equals 293 (PolicyParser.PrincipalEntry.WILDCARD_CLASS) || 294 pppe.principalClass.equals 295 (listPppe.principalClass)) { 296 297 if (pppe.principalName.equals 298 (PolicyParser.PrincipalEntry.WILDCARD_NAME) || 299 pppe.principalName.equals 300 (listPppe.principalName)) 301 return true; 302 } 303 } 304 return false; 305 } 306 307 /** 308 * Tests for equality between the specified object and this 309 * object. Two <code>SubjectCodeSource</code> objects are considered equal 310 * if their locations are of identical value, if the two sets of 311 * Certificates are of identical values, and if the 312 * Subjects are equal, and if the PolicyParser.PrincipalEntry values 313 * are of identical values. It is not required that 314 * the Certificates or PolicyParser.PrincipalEntry values 315 * be in the same order. 316 * 317 * <p> 318 * 319 * @param obj the object to test for equality with this object. 320 * 321 * @return true if the objects are considered equal, false otherwise. 322 */ 323 public boolean equals(Object obj) { 324 325 if (obj == this) 326 return true; 327 328 if (super.equals(obj) == false) 329 return false; 330 331 if (!(obj instanceof SubjectCodeSource)) 332 return false; 333 334 SubjectCodeSource that = (SubjectCodeSource)obj; 335 336 // the principal lists must match 337 try { 338 if (this.getSubject() != that.getSubject()) 339 return false; 340 } catch (SecurityException se) { 341 return false; 342 } 343 344 if ((this.principals == null && that.principals != null) || 345 (this.principals != null && that.principals == null)) 346 return false; 347 348 if (this.principals != null && that.principals != null) { 349 if (!this.principals.containsAll(that.principals) || 350 !that.principals.containsAll(this.principals)) 351 352 return false; 353 } 354 355 return true; 356 } 357 358 /** 359 * Return a hashcode for this <code>SubjectCodeSource</code>. 360 * 361 * <p> 362 * 363 * @return a hashcode for this <code>SubjectCodeSource</code>. 364 */ 365 public int hashCode() { 366 return super.hashCode(); 367 } 368 369 /** 370 * Return a String representation of this <code>SubjectCodeSource</code>. 371 * 372 * <p> 373 * 374 * @return a String representation of this <code>SubjectCodeSource</code>. 375 */ 376 public String toString() { 377 String returnMe = super.toString(); 378 if (getSubject() != null) { 379 if (debug != null) { 380 final Subject finalSubject = getSubject(); 381 returnMe = returnMe + "\n" + 382 java.security.AccessController.doPrivileged 383 (new java.security.PrivilegedAction<String>() { 384 public String run() { 385 return finalSubject.toString(); 386 } 387 }); 388 } else { 389 returnMe = returnMe + "\n" + getSubject().toString(); 390 } 391 } 392 if (principals != null) { 393 ListIterator<PolicyParser.PrincipalEntry> li = 394 principals.listIterator(); 395 while (li.hasNext()) { 396 PolicyParser.PrincipalEntry pppe = li.next(); 397 returnMe = returnMe + rb.getString("NEWLINE") + 398 pppe.principalClass + " " + 399 pppe.principalName; 400 } 401 } 402 return returnMe; 403 } 404 }