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