1 package org.bouncycastle.x509; 2 3 import org.bouncycastle.asn1.ASN1InputStream; 4 import org.bouncycastle.asn1.ASN1Object; 5 import org.bouncycastle.asn1.ASN1Primitive; 6 import org.bouncycastle.asn1.DEROctetString; 7 import org.bouncycastle.asn1.x509.GeneralName; 8 import org.bouncycastle.asn1.x509.Target; 9 import org.bouncycastle.asn1.x509.TargetInformation; 10 import org.bouncycastle.asn1.x509.Targets; 11 import org.bouncycastle.asn1.x509.X509Extensions; 12 import org.bouncycastle.util.Selector; 13 14 import java.io.IOException; 15 import java.math.BigInteger; 16 import java.security.cert.CertificateExpiredException; 17 import java.security.cert.CertificateNotYetValidException; 18 import java.security.cert.X509CertSelector; 19 import java.util.Collection; 20 import java.util.Collections; 21 import java.util.Date; 22 import java.util.HashSet; 23 import java.util.Iterator; 24 import java.util.Set; 25 26 /** 27 * This class is an <code>Selector</code> like implementation to select 28 * attribute certificates from a given set of criteria. 29 * 30 * @see org.bouncycastle.x509.X509AttributeCertificate 31 * @see org.bouncycastle.x509.X509Store 32 */ 33 public class X509AttributeCertStoreSelector 34 implements Selector 35 { 36 37 // TODO: name constraints??? 38 39 private AttributeCertificateHolder holder; 40 41 private AttributeCertificateIssuer issuer; 42 43 private BigInteger serialNumber; 44 45 private Date attributeCertificateValid; 46 47 private X509AttributeCertificate attributeCert; 48 49 private Collection targetNames = new HashSet(); 50 51 private Collection targetGroups = new HashSet(); 52 X509AttributeCertStoreSelector()53 public X509AttributeCertStoreSelector() 54 { 55 super(); 56 } 57 58 /** 59 * Decides if the given attribute certificate should be selected. 60 * 61 * @param obj The attribute certificate which should be checked. 62 * @return <code>true</code> if the attribute certificate can be selected, 63 * <code>false</code> otherwise. 64 */ match(Object obj)65 public boolean match(Object obj) 66 { 67 if (!(obj instanceof X509AttributeCertificate)) 68 { 69 return false; 70 } 71 72 X509AttributeCertificate attrCert = (X509AttributeCertificate) obj; 73 74 if (this.attributeCert != null) 75 { 76 if (!this.attributeCert.equals(attrCert)) 77 { 78 return false; 79 } 80 } 81 if (serialNumber != null) 82 { 83 if (!attrCert.getSerialNumber().equals(serialNumber)) 84 { 85 return false; 86 } 87 } 88 if (holder != null) 89 { 90 if (!attrCert.getHolder().equals(holder)) 91 { 92 return false; 93 } 94 } 95 if (issuer != null) 96 { 97 if (!attrCert.getIssuer().equals(issuer)) 98 { 99 return false; 100 } 101 } 102 103 if (attributeCertificateValid != null) 104 { 105 try 106 { 107 attrCert.checkValidity(attributeCertificateValid); 108 } 109 catch (CertificateExpiredException e) 110 { 111 return false; 112 } 113 catch (CertificateNotYetValidException e) 114 { 115 return false; 116 } 117 } 118 if (!targetNames.isEmpty() || !targetGroups.isEmpty()) 119 { 120 121 byte[] targetInfoExt = attrCert 122 .getExtensionValue(X509Extensions.TargetInformation.getId()); 123 if (targetInfoExt != null) 124 { 125 TargetInformation targetinfo; 126 try 127 { 128 targetinfo = TargetInformation 129 .getInstance(new ASN1InputStream( 130 ((DEROctetString) DEROctetString 131 .fromByteArray(targetInfoExt)).getOctets()) 132 .readObject()); 133 } 134 catch (IOException e) 135 { 136 return false; 137 } 138 catch (IllegalArgumentException e) 139 { 140 return false; 141 } 142 Targets[] targetss = targetinfo.getTargetsObjects(); 143 if (!targetNames.isEmpty()) 144 { 145 boolean found = false; 146 147 for (int i=0; i<targetss.length; i++) 148 { 149 Targets t = targetss[i]; 150 Target[] targets = t.getTargets(); 151 for (int j=0; j<targets.length; j++) 152 { 153 if (targetNames.contains(targets[j] 154 .getTargetName())) 155 { 156 found = true; 157 break; 158 } 159 } 160 } 161 if (!found) 162 { 163 return false; 164 } 165 } 166 if (!targetGroups.isEmpty()) 167 { 168 boolean found = false; 169 170 for (int i=0; i<targetss.length; i++) 171 { 172 Targets t = targetss[i]; 173 Target[] targets = t.getTargets(); 174 for (int j=0; j<targets.length; j++) 175 { 176 if (targetGroups.contains(targets[j] 177 .getTargetGroup())) 178 { 179 found = true; 180 break; 181 } 182 } 183 } 184 if (!found) 185 { 186 return false; 187 } 188 } 189 } 190 } 191 return true; 192 } 193 194 /** 195 * Returns a clone of this object. 196 * 197 * @return the clone. 198 */ clone()199 public Object clone() 200 { 201 X509AttributeCertStoreSelector sel = new X509AttributeCertStoreSelector(); 202 sel.attributeCert = attributeCert; 203 sel.attributeCertificateValid = getAttributeCertificateValid(); 204 sel.holder = holder; 205 sel.issuer = issuer; 206 sel.serialNumber = serialNumber; 207 sel.targetGroups = getTargetGroups(); 208 sel.targetNames = getTargetNames(); 209 return sel; 210 } 211 212 /** 213 * Returns the attribute certificate which must be matched. 214 * 215 * @return Returns the attribute certificate. 216 */ getAttributeCert()217 public X509AttributeCertificate getAttributeCert() 218 { 219 return attributeCert; 220 } 221 222 /** 223 * Set the attribute certificate to be matched. If <code>null</code> is 224 * given any will do. 225 * 226 * @param attributeCert The attribute certificate to set. 227 */ setAttributeCert(X509AttributeCertificate attributeCert)228 public void setAttributeCert(X509AttributeCertificate attributeCert) 229 { 230 this.attributeCert = attributeCert; 231 } 232 233 /** 234 * Get the criteria for the validity. 235 * 236 * @return Returns the attributeCertificateValid. 237 */ getAttributeCertificateValid()238 public Date getAttributeCertificateValid() 239 { 240 if (attributeCertificateValid != null) 241 { 242 return new Date(attributeCertificateValid.getTime()); 243 } 244 245 return null; 246 } 247 248 /** 249 * Set the time, when the certificate must be valid. If <code>null</code> 250 * is given any will do. 251 * 252 * @param attributeCertificateValid The attribute certificate validation 253 * time to set. 254 */ setAttributeCertificateValid(Date attributeCertificateValid)255 public void setAttributeCertificateValid(Date attributeCertificateValid) 256 { 257 if (attributeCertificateValid != null) 258 { 259 this.attributeCertificateValid = new Date(attributeCertificateValid 260 .getTime()); 261 } 262 else 263 { 264 this.attributeCertificateValid = null; 265 } 266 } 267 268 /** 269 * Gets the holder. 270 * 271 * @return Returns the holder. 272 */ getHolder()273 public AttributeCertificateHolder getHolder() 274 { 275 return holder; 276 } 277 278 /** 279 * Sets the holder. If <code>null</code> is given any will do. 280 * 281 * @param holder The holder to set. 282 */ setHolder(AttributeCertificateHolder holder)283 public void setHolder(AttributeCertificateHolder holder) 284 { 285 this.holder = holder; 286 } 287 288 /** 289 * Returns the issuer criterion. 290 * 291 * @return Returns the issuer. 292 */ getIssuer()293 public AttributeCertificateIssuer getIssuer() 294 { 295 return issuer; 296 } 297 298 /** 299 * Sets the issuer the attribute certificate must have. If <code>null</code> 300 * is given any will do. 301 * 302 * @param issuer The issuer to set. 303 */ setIssuer(AttributeCertificateIssuer issuer)304 public void setIssuer(AttributeCertificateIssuer issuer) 305 { 306 this.issuer = issuer; 307 } 308 309 /** 310 * Gets the serial number the attribute certificate must have. 311 * 312 * @return Returns the serialNumber. 313 */ getSerialNumber()314 public BigInteger getSerialNumber() 315 { 316 return serialNumber; 317 } 318 319 /** 320 * Sets the serial number the attribute certificate must have. If 321 * <code>null</code> is given any will do. 322 * 323 * @param serialNumber The serialNumber to set. 324 */ setSerialNumber(BigInteger serialNumber)325 public void setSerialNumber(BigInteger serialNumber) 326 { 327 this.serialNumber = serialNumber; 328 } 329 330 /** 331 * Adds a target name criterion for the attribute certificate to the target 332 * information extension criteria. The <code>X509AttributeCertificate</code> 333 * must contain at least one of the specified target names. 334 * <p> 335 * Each attribute certificate may contain a target information extension 336 * limiting the servers where this attribute certificate can be used. If 337 * this extension is not present, the attribute certificate is not targeted 338 * and may be accepted by any server. 339 * 340 * @param name The name as a GeneralName (not <code>null</code>) 341 */ addTargetName(GeneralName name)342 public void addTargetName(GeneralName name) 343 { 344 targetNames.add(name); 345 } 346 347 /** 348 * Adds a target name criterion for the attribute certificate to the target 349 * information extension criteria. The <code>X509AttributeCertificate</code> 350 * must contain at least one of the specified target names. 351 * <p> 352 * Each attribute certificate may contain a target information extension 353 * limiting the servers where this attribute certificate can be used. If 354 * this extension is not present, the attribute certificate is not targeted 355 * and may be accepted by any server. 356 * 357 * @param name a byte array containing the name in ASN.1 DER encoded form of a GeneralName 358 * @throws IOException if a parsing error occurs. 359 */ addTargetName(byte[] name)360 public void addTargetName(byte[] name) throws IOException 361 { 362 addTargetName(GeneralName.getInstance(ASN1Primitive.fromByteArray(name))); 363 } 364 365 /** 366 * Adds a collection with target names criteria. If <code>null</code> is 367 * given any will do. 368 * <p> 369 * The collection consists of either GeneralName objects or byte[] arrays representing 370 * DER encoded GeneralName structures. 371 * 372 * @param names A collection of target names. 373 * @throws IOException if a parsing error occurs. 374 * @see #addTargetName(byte[]) 375 * @see #addTargetName(GeneralName) 376 */ setTargetNames(Collection names)377 public void setTargetNames(Collection names) throws IOException 378 { 379 targetNames = extractGeneralNames(names); 380 } 381 382 /** 383 * Gets the target names. The collection consists of <code>List</code>s 384 * made up of an <code>Integer</code> in the first entry and a DER encoded 385 * byte array or a <code>String</code> in the second entry. 386 * <p> 387 * The returned collection is immutable. 388 * 389 * @return The collection of target names 390 * @see #setTargetNames(Collection) 391 */ getTargetNames()392 public Collection getTargetNames() 393 { 394 return Collections.unmodifiableCollection(targetNames); 395 } 396 397 /** 398 * Adds a target group criterion for the attribute certificate to the target 399 * information extension criteria. The <code>X509AttributeCertificate</code> 400 * must contain at least one of the specified target groups. 401 * <p> 402 * Each attribute certificate may contain a target information extension 403 * limiting the servers where this attribute certificate can be used. If 404 * this extension is not present, the attribute certificate is not targeted 405 * and may be accepted by any server. 406 * 407 * @param group The group as GeneralName form (not <code>null</code>) 408 */ addTargetGroup(GeneralName group)409 public void addTargetGroup(GeneralName group) 410 { 411 targetGroups.add(group); 412 } 413 414 /** 415 * Adds a target group criterion for the attribute certificate to the target 416 * information extension criteria. The <code>X509AttributeCertificate</code> 417 * must contain at least one of the specified target groups. 418 * <p> 419 * Each attribute certificate may contain a target information extension 420 * limiting the servers where this attribute certificate can be used. If 421 * this extension is not present, the attribute certificate is not targeted 422 * and may be accepted by any server. 423 * 424 * @param name a byte array containing the group in ASN.1 DER encoded form of a GeneralName 425 * @throws IOException if a parsing error occurs. 426 */ addTargetGroup(byte[] name)427 public void addTargetGroup(byte[] name) throws IOException 428 { 429 addTargetGroup(GeneralName.getInstance(ASN1Primitive.fromByteArray(name))); 430 } 431 432 /** 433 * Adds a collection with target groups criteria. If <code>null</code> is 434 * given any will do. 435 * <p> 436 * The collection consists of <code>GeneralName</code> objects or <code>byte[]</code representing DER 437 * encoded GeneralNames. 438 * 439 * @param names A collection of target groups. 440 * @throws IOException if a parsing error occurs. 441 * @see #addTargetGroup(byte[]) 442 * @see #addTargetGroup(GeneralName) 443 */ setTargetGroups(Collection names)444 public void setTargetGroups(Collection names) throws IOException 445 { 446 targetGroups = extractGeneralNames(names); 447 } 448 449 450 451 /** 452 * Gets the target groups. The collection consists of <code>List</code>s 453 * made up of an <code>Integer</code> in the first entry and a DER encoded 454 * byte array or a <code>String</code> in the second entry. 455 * <p> 456 * The returned collection is immutable. 457 * 458 * @return The collection of target groups. 459 * @see #setTargetGroups(Collection) 460 */ getTargetGroups()461 public Collection getTargetGroups() 462 { 463 return Collections.unmodifiableCollection(targetGroups); 464 } 465 extractGeneralNames(Collection names)466 private Set extractGeneralNames(Collection names) 467 throws IOException 468 { 469 if (names == null || names.isEmpty()) 470 { 471 return new HashSet(); 472 } 473 Set temp = new HashSet(); 474 for (Iterator it = names.iterator(); it.hasNext();) 475 { 476 Object o = it.next(); 477 if (o instanceof GeneralName) 478 { 479 temp.add(o); 480 } 481 else 482 { 483 temp.add(GeneralName.getInstance(ASN1Primitive.fromByteArray((byte[])o))); 484 } 485 } 486 return temp; 487 } 488 } 489