using System; using System.Collections.Generic; using Org.BouncyCastle.Asn1; using Org.BouncyCastle.Asn1.X509; using Org.BouncyCastle.Math; using Org.BouncyCastle.Utilities.Collections; using Org.BouncyCastle.X509.Extension; namespace Org.BouncyCastle.X509.Store { /** * This class is an Selector like implementation to select * attribute certificates from a given set of criteria. * * @see org.bouncycastle.x509.X509AttributeCertificate * @see org.bouncycastle.x509.X509Store */ public class X509AttrCertStoreSelector : ISelector { // TODO: name constraints??? private X509V2AttributeCertificate attributeCert; private DateTime? attributeCertificateValid; private AttributeCertificateHolder holder; private AttributeCertificateIssuer issuer; private BigInteger serialNumber; private ISet targetNames = new HashSet(); private ISet targetGroups = new HashSet(); public X509AttrCertStoreSelector() { } private X509AttrCertStoreSelector( X509AttrCertStoreSelector o) { this.attributeCert = o.attributeCert; this.attributeCertificateValid = o.attributeCertificateValid; this.holder = o.holder; this.issuer = o.issuer; this.serialNumber = o.serialNumber; this.targetGroups = new HashSet(o.targetGroups); this.targetNames = new HashSet(o.targetNames); } /// /// Decides if the given attribute certificate should be selected. /// /// The attribute certificate to be checked. /// true if the object matches this selector. public bool Match(X509V2AttributeCertificate attrCert) { if (attrCert == null) return false; if (this.attributeCert != null && !this.attributeCert.Equals(attrCert)) return false; if (serialNumber != null && !attrCert.SerialNumber.Equals(serialNumber)) return false; if (holder != null && !attrCert.Holder.Equals(holder)) return false; if (issuer != null && !attrCert.Issuer.Equals(issuer)) return false; if (attributeCertificateValid != null && !attrCert.IsValid(attributeCertificateValid.Value)) return false; if (targetNames.Count > 0 || targetGroups.Count > 0) { Asn1OctetString targetInfoExt = attrCert.GetExtensionValue(X509Extensions.TargetInformation); if (targetInfoExt != null) { TargetInformation targetinfo; try { targetinfo = TargetInformation.GetInstance( X509ExtensionUtilities.FromExtensionValue(targetInfoExt)); } catch (Exception) { return false; } Targets[] targetss = targetinfo.GetTargetsObjects(); if (targetNames.Count > 0) { bool found = false; for (int i = 0; i < targetss.Length && !found; i++) { Target[] targets = targetss[i].GetTargets(); for (int j = 0; j < targets.Length; j++) { GeneralName targetName = targets[j].TargetName; if (targetName != null && targetNames.Contains(targetName)) { found = true; break; } } } if (!found) return false; } if (targetGroups.Count > 0) { bool found = false; for (int i = 0; i < targetss.Length && !found; i++) { Target[] targets = targetss[i].GetTargets(); for (int j = 0; j < targets.Length; j++) { GeneralName targetGroup = targets[j].TargetGroup; if (targetGroup != null && targetGroups.Contains(targetGroup)) { found = true; break; } } } if (!found) return false; } } } return true; } public object Clone() { return new X509AttrCertStoreSelector(this); } /// The attribute certificate which must be matched. /// If null is given, any will do. public X509V2AttributeCertificate AttributeCert { get { return attributeCert; } set { this.attributeCert = value; } } /// The criteria for validity /// If null is given any will do. public DateTime? AttributeCertificateValid { get { return attributeCertificateValid; } set { this.attributeCertificateValid = value; } } /// The holder. /// If null is given any will do. public AttributeCertificateHolder Holder { get { return holder; } set { this.holder = value; } } /// The issuer. /// If null is given any will do. public AttributeCertificateIssuer Issuer { get { return issuer; } set { this.issuer = value; } } /// The serial number. /// If null is given any will do. public BigInteger SerialNumber { get { return serialNumber; } set { this.serialNumber = value; } } /** * Adds a target name criterion for the attribute certificate to the target * information extension criteria. The X509AttributeCertificate * must contain at least one of the specified target names. *

* Each attribute certificate may contain a target information extension * limiting the servers where this attribute certificate can be used. If * this extension is not present, the attribute certificate is not targeted * and may be accepted by any server. *

* * @param name The name as a GeneralName (not null) */ public void AddTargetName(GeneralName name) { targetNames.Add(name); } /** * Adds a target name criterion for the attribute certificate to the target * information extension criteria. The X509AttributeCertificate * must contain at least one of the specified target names. *

* Each attribute certificate may contain a target information extension * limiting the servers where this attribute certificate can be used. If * this extension is not present, the attribute certificate is not targeted * and may be accepted by any server. *

* * @param name a byte array containing the name in ASN.1 DER encoded form of a GeneralName * @throws IOException if a parsing error occurs. */ public void AddTargetName(byte[] name) { AddTargetName(GeneralName.GetInstance(Asn1Object.FromByteArray(name))); } /** * Adds a collection with target names criteria. If null is * given any will do. *

* The collection consists of either GeneralName objects or byte[] arrays representing * DER encoded GeneralName structures. *

* * @param names A collection of target names. * @throws IOException if a parsing error occurs. * @see #AddTargetName(byte[]) * @see #AddTargetName(GeneralName) */ public void SetTargetNames(IEnumerable names) { targetNames = ExtractGeneralNames(names); } /** * Gets the target names. The collection consists of Lists * made up of an Integer in the first entry and a DER encoded * byte array or a String in the second entry. *

The returned collection is immutable.

* * @return The collection of target names * @see #setTargetNames(Collection) */ public IEnumerable GetTargetNames() { return CollectionUtilities.Proxy(targetNames); } /** * Adds a target group criterion for the attribute certificate to the target * information extension criteria. The X509AttributeCertificate * must contain at least one of the specified target groups. *

* Each attribute certificate may contain a target information extension * limiting the servers where this attribute certificate can be used. If * this extension is not present, the attribute certificate is not targeted * and may be accepted by any server. *

* * @param group The group as GeneralName form (not null) */ public void AddTargetGroup(GeneralName group) { targetGroups.Add(group); } /** * Adds a target group criterion for the attribute certificate to the target * information extension criteria. The X509AttributeCertificate * must contain at least one of the specified target groups. *

* Each attribute certificate may contain a target information extension * limiting the servers where this attribute certificate can be used. If * this extension is not present, the attribute certificate is not targeted * and may be accepted by any server. *

* * @param name a byte array containing the group in ASN.1 DER encoded form of a GeneralName * @throws IOException if a parsing error occurs. */ public void AddTargetGroup(byte[] name) { AddTargetGroup(GeneralName.GetInstance(Asn1Object.FromByteArray(name))); } /** * Adds a collection with target groups criteria. If null is * given any will do. *

* The collection consists of GeneralName objects or byte[] * representing DER encoded GeneralNames. *

* * @param names A collection of target groups. * @throws IOException if a parsing error occurs. * @see #AddTargetGroup(byte[]) * @see #AddTargetGroup(GeneralName) */ public void SetTargetGroups(IEnumerable names) { targetGroups = ExtractGeneralNames(names); } /** * Gets the target groups. The collection consists of Lists * made up of an Integer in the first entry and a DER encoded * byte array or a String in the second entry. *

The returned collection is immutable.

* * @return The collection of target groups. * @see #setTargetGroups(Collection) */ public IEnumerable GetTargetGroups() { return CollectionUtilities.Proxy(targetGroups); } private ISet ExtractGeneralNames(IEnumerable names) { var result = new HashSet(); if (names != null) { foreach (object o in names) { result.Add(GeneralName.GetInstance(o)); } } return result; } } }