001: package org.bouncycastle.x509;
002:
003: import org.bouncycastle.asn1.ASN1InputStream;
004: import org.bouncycastle.asn1.ASN1Object;
005: import org.bouncycastle.asn1.DEROctetString;
006: import org.bouncycastle.asn1.x509.GeneralName;
007: import org.bouncycastle.asn1.x509.Target;
008: import org.bouncycastle.asn1.x509.TargetInformation;
009: import org.bouncycastle.asn1.x509.Targets;
010: import org.bouncycastle.asn1.x509.X509Extensions;
011: import org.bouncycastle.util.Selector;
012:
013: import java.io.IOException;
014: import java.math.BigInteger;
015: import java.security.cert.CertificateExpiredException;
016: import java.security.cert.CertificateNotYetValidException;
017: import java.util.Collection;
018: import java.util.Collections;
019: import java.util.Date;
020: import java.util.HashSet;
021: import java.util.Iterator;
022: import java.util.Set;
023:
024: /**
025: * This class is an <code>Selector</code> like implementation to select
026: * attribute certificates from a given set of criteria.
027: *
028: * @see org.bouncycastle.x509.X509AttributeCertificate
029: * @see org.bouncycastle.x509.X509Store
030: */
031: public class X509AttributeCertStoreSelector implements Selector {
032:
033: // TODO: name constraints???
034:
035: private AttributeCertificateHolder holder;
036:
037: private AttributeCertificateIssuer issuer;
038:
039: private BigInteger serialNumber;
040:
041: private Date attributeCertificateValid;
042:
043: private X509AttributeCertificate attributeCert;
044:
045: private Collection targetNames = new HashSet();
046:
047: private Collection targetGroups = new HashSet();
048:
049: public X509AttributeCertStoreSelector() {
050: super ();
051: }
052:
053: /**
054: * Decides if the given attribute certificate should be selected.
055: *
056: * @param obj The attribute certificate which should be checked.
057: * @return <code>true</code> if the attribute certificate can be selected,
058: * <code>false</code> otherwise.
059: */
060: public boolean match(Object obj) {
061: if (!(obj instanceof X509AttributeCertificate)) {
062: return false;
063: }
064:
065: X509AttributeCertificate attrCert = (X509AttributeCertificate) obj;
066:
067: if (this .attributeCert != null) {
068: if (!this .attributeCert.equals(attrCert)) {
069: return false;
070: }
071: }
072: if (serialNumber != null) {
073: if (!attrCert.getSerialNumber().equals(serialNumber)) {
074: return false;
075: }
076: }
077: if (holder != null) {
078: if (!attrCert.getHolder().equals(holder)) {
079: return false;
080: }
081: }
082: if (issuer != null) {
083: if (!attrCert.getIssuer().equals(issuer)) {
084: return false;
085: }
086: }
087:
088: if (attributeCertificateValid != null) {
089: try {
090: attrCert.checkValidity(attributeCertificateValid);
091: } catch (CertificateExpiredException e) {
092: return false;
093: } catch (CertificateNotYetValidException e) {
094: return false;
095: }
096: }
097: if (!targetNames.isEmpty() || !targetGroups.isEmpty()) {
098:
099: byte[] targetInfoExt = attrCert
100: .getExtensionValue(X509Extensions.TargetInformation
101: .getId());
102: if (targetInfoExt != null) {
103: TargetInformation targetinfo;
104: try {
105: targetinfo = TargetInformation
106: .getInstance(new ASN1InputStream(
107: ((DEROctetString) DEROctetString
108: .fromByteArray(targetInfoExt))
109: .getOctets()).readObject());
110: } catch (IOException e) {
111: return false;
112: } catch (IllegalArgumentException e) {
113: return false;
114: }
115: Targets[] targetss = targetinfo.getTargetsObjects();
116: if (!targetNames.isEmpty()) {
117: boolean found = false;
118:
119: for (int i = 0; i < targetss.length; i++) {
120: Targets t = targetss[i];
121: Target[] targets = t.getTargets();
122: for (int j = 0; j < targets.length; j++) {
123: if (targetNames.contains(targets[j]
124: .getTargetName())) {
125: found = true;
126: break;
127: }
128: }
129: }
130: if (!found) {
131: return false;
132: }
133: }
134: if (!targetGroups.isEmpty()) {
135: boolean found = false;
136:
137: for (int i = 0; i < targetss.length; i++) {
138: Targets t = targetss[i];
139: Target[] targets = t.getTargets();
140: for (int j = 0; j < targets.length; j++) {
141: if (targetGroups.contains(targets[j]
142: .getTargetGroup())) {
143: found = true;
144: break;
145: }
146: }
147: }
148: if (!found) {
149: return false;
150: }
151: }
152: }
153: }
154: return true;
155: }
156:
157: /**
158: * Returns a clone of this object.
159: *
160: * @return the clone.
161: */
162: public Object clone() {
163: X509AttributeCertStoreSelector sel = new X509AttributeCertStoreSelector();
164: sel.attributeCert = attributeCert;
165: sel.attributeCertificateValid = getAttributeCertificateValid();
166: sel.holder = holder;
167: sel.issuer = issuer;
168: sel.serialNumber = serialNumber;
169: sel.targetGroups = getTargetGroups();
170: sel.targetNames = getTargetNames();
171: return sel;
172: }
173:
174: /**
175: * Returns the attribute certificate which must be matched.
176: *
177: * @return Returns the attribute certificate.
178: */
179: public X509AttributeCertificate getAttributeCert() {
180: return attributeCert;
181: }
182:
183: /**
184: * Set the attribute certificate to be matched. If <code>null</code> is
185: * given any will do.
186: *
187: * @param attributeCert The attribute certificate to set.
188: */
189: public void setAttributeCert(X509AttributeCertificate attributeCert) {
190: this .attributeCert = attributeCert;
191: }
192:
193: /**
194: * Get the criteria for the validity.
195: *
196: * @return Returns the attributeCertificateValid.
197: */
198: public Date getAttributeCertificateValid() {
199: if (attributeCertificateValid != null) {
200: return new Date(attributeCertificateValid.getTime());
201: }
202:
203: return null;
204: }
205:
206: /**
207: * Set the time, when the certificate must be valid. If <code>null</code>
208: * is given any will do.
209: *
210: * @param attributeCertificateValid The attribute certificate validation
211: * time to set.
212: */
213: public void setAttributeCertificateValid(
214: Date attributeCertificateValid) {
215: if (attributeCertificateValid != null) {
216: this .attributeCertificateValid = new Date(
217: attributeCertificateValid.getTime());
218: } else {
219: this .attributeCertificateValid = null;
220: }
221: }
222:
223: /**
224: * Gets the holder.
225: *
226: * @return Returns the holder.
227: */
228: public AttributeCertificateHolder getHolder() {
229: return holder;
230: }
231:
232: /**
233: * Sets the holder. If <code>null</code> is given any will do.
234: *
235: * @param holder The holder to set.
236: */
237: public void setHolder(AttributeCertificateHolder holder) {
238: this .holder = holder;
239: }
240:
241: /**
242: * Returns the issuer criterion.
243: *
244: * @return Returns the issuer.
245: */
246: public AttributeCertificateIssuer getIssuer() {
247: return issuer;
248: }
249:
250: /**
251: * Sets the issuer the attribute certificate must have. If <code>null</code>
252: * is given any will do.
253: *
254: * @param issuer The issuer to set.
255: */
256: public void setIssuer(AttributeCertificateIssuer issuer) {
257: this .issuer = issuer;
258: }
259:
260: /**
261: * Gets the serial number the attribute certificate must have.
262: *
263: * @return Returns the serialNumber.
264: */
265: public BigInteger getSerialNumber() {
266: return serialNumber;
267: }
268:
269: /**
270: * Sets the serial number the attribute certificate must have. If
271: * <code>null</code> is given any will do.
272: *
273: * @param serialNumber The serialNumber to set.
274: */
275: public void setSerialNumber(BigInteger serialNumber) {
276: this .serialNumber = serialNumber;
277: }
278:
279: /**
280: * Adds a target name criterion for the attribute certificate to the target
281: * information extension criteria. The <code>X509AttributeCertificate</code>
282: * must contain at least one of the specified target names.
283: * <p>
284: * Each attribute certificate may contain a target information extension
285: * limiting the servers where this attribute certificate can be used. If
286: * this extension is not present, the attribute certificate is not targeted
287: * and may be accepted by any server.
288: *
289: * @param name The name as a GeneralName (not <code>null</code>)
290: */
291: public void addTargetName(GeneralName name) {
292: targetNames.add(name);
293: }
294:
295: /**
296: * Adds a target name criterion for the attribute certificate to the target
297: * information extension criteria. The <code>X509AttributeCertificate</code>
298: * must contain at least one of the specified target names.
299: * <p>
300: * Each attribute certificate may contain a target information extension
301: * limiting the servers where this attribute certificate can be used. If
302: * this extension is not present, the attribute certificate is not targeted
303: * and may be accepted by any server.
304: *
305: * @param name a byte array containing the name in ASN.1 DER encoded form of a GeneralName
306: * @throws IOException if a parsing error occurs.
307: */
308: public void addTargetName(byte[] name) throws IOException {
309: addTargetName(GeneralName.getInstance(ASN1Object
310: .fromByteArray(name)));
311: }
312:
313: /**
314: * Adds a collection with target names criteria. If <code>null</code> is
315: * given any will do.
316: * <p>
317: * The collection consists of either GeneralName objects or byte[] arrays representing
318: * DER encoded GeneralName structures.
319: *
320: * @param names A collection of target names.
321: * @throws IOException if a parsing error occurs.
322: * @see #addTargetName(byte[])
323: * @see #addTargetName(GeneralName)
324: */
325: public void setTargetNames(Collection names) throws IOException {
326: targetNames = extractGeneralNames(names);
327: }
328:
329: /**
330: * Gets the target names. The collection consists of <code>List</code>s
331: * made up of an <code>Integer</code> in the first entry and a DER encoded
332: * byte array or a <code>String</code> in the second entry.
333: * <p>
334: * The returned collection is immutable.
335: *
336: * @return The collection of target names
337: * @see #setTargetNames(Collection)
338: */
339: public Collection getTargetNames() {
340: return Collections.unmodifiableCollection(targetNames);
341: }
342:
343: /**
344: * Adds a target group criterion for the attribute certificate to the target
345: * information extension criteria. The <code>X509AttributeCertificate</code>
346: * must contain at least one of the specified target groups.
347: * <p>
348: * Each attribute certificate may contain a target information extension
349: * limiting the servers where this attribute certificate can be used. If
350: * this extension is not present, the attribute certificate is not targeted
351: * and may be accepted by any server.
352: *
353: * @param group The group as GeneralName form (not <code>null</code>)
354: */
355: public void addTargetGroup(GeneralName group) {
356: targetGroups.add(group);
357: }
358:
359: /**
360: * Adds a target group criterion for the attribute certificate to the target
361: * information extension criteria. The <code>X509AttributeCertificate</code>
362: * must contain at least one of the specified target groups.
363: * <p>
364: * Each attribute certificate may contain a target information extension
365: * limiting the servers where this attribute certificate can be used. If
366: * this extension is not present, the attribute certificate is not targeted
367: * and may be accepted by any server.
368: *
369: * @param name a byte array containing the group in ASN.1 DER encoded form of a GeneralName
370: * @throws IOException if a parsing error occurs.
371: */
372: public void addTargetGroup(byte[] name) throws IOException {
373: addTargetGroup(GeneralName.getInstance(ASN1Object
374: .fromByteArray(name)));
375: }
376:
377: /**
378: * Adds a collection with target groups criteria. If <code>null</code> is
379: * given any will do.
380: * <p>
381: * The collection consists of <code>GeneralName</code> objects or <code>byte[]</code representing DER
382: * encoded GeneralNames.
383: *
384: * @param names A collection of target groups.
385: * @throws IOException if a parsing error occurs.
386: * @see #addTargetGroup(byte[])
387: * @see #addTargetGroup(GeneralName)
388: */
389: public void setTargetGroups(Collection names) throws IOException {
390: targetGroups = extractGeneralNames(names);
391: }
392:
393: /**
394: * Gets the target groups. The collection consists of <code>List</code>s
395: * made up of an <code>Integer</code> in the first entry and a DER encoded
396: * byte array or a <code>String</code> in the second entry.
397: * <p>
398: * The returned collection is immutable.
399: *
400: * @return The collection of target groups.
401: * @see #setTargetGroups(Collection)
402: */
403: public Collection getTargetGroups() {
404: return Collections.unmodifiableCollection(targetGroups);
405: }
406:
407: private Set extractGeneralNames(Collection names)
408: throws IOException {
409: if (names == null || names.isEmpty()) {
410: return new HashSet();
411: }
412: Set temp = new HashSet();
413: for (Iterator it = names.iterator(); it.hasNext();) {
414: Object o = it.next();
415: if (o instanceof GeneralName) {
416: temp.add(o);
417: } else {
418: temp.add(GeneralName.getInstance(ASN1Object
419: .fromByteArray((byte[]) o)));
420: }
421: }
422: return temp;
423: }
424: }
|