Coverage Report - org.openpermis.cert.AttributeCertificateExtractorUtility
 
Classes in this File Line Coverage Branch Coverage Complexity
AttributeCertificateExtractorUtility
37%
20/53
30%
8/26
3.818
 
 1  
 /*
 2  
  * Copyright (c) 2009, Swiss Federal Department of Defence Civil Protection and Sport
 3  
  *                     (http://www.vbs.admin.ch)
 4  
  * Copyright (c) 2009, Ergon Informatik AG (http://www.ergon.ch)
 5  
  * All rights reserved.
 6  
  *
 7  
  * Licensed under the Open Permis License which accompanies this distribution,
 8  
  * and is available at http://www.openpermis.org/BSDlicenceKent.txt
 9  
  */
 10  
 package org.openpermis.cert;
 11  
 
 12  
 import java.io.IOException;
 13  
 import java.io.StringReader;
 14  
 import java.net.URI;
 15  
 import java.net.URL;
 16  
 import java.security.Principal;
 17  
 import java.security.cert.CertificateException;
 18  
 import java.util.List;
 19  
 
 20  
 import javax.security.auth.x500.X500Principal;
 21  
 
 22  
 import org.bouncycastle.util.StreamParsingException;
 23  
 import org.bouncycastle.x509.X509Attribute;
 24  
 
 25  
 import org.openpermis.PolicyDecisionPoint;
 26  
 import org.openpermis.basic.AbsoluteTimePeriod;
 27  
 import org.openpermis.basic.ExpirablePolicyDecisionPoint;
 28  
 import org.openpermis.basic.TimePeriod;
 29  
 import org.openpermis.cert.RoleAttribute.RoleDefinition;
 30  
 import org.openpermis.policy.bean.basic.BasicPartBeanFactory;
 31  
 import org.openpermis.policy.io.PolicyException;
 32  
 import org.openpermis.policy.io.PolicyReader;
 33  
 import org.openpermis.policy.io.StrictPolicyReader;
 34  
 import org.openpermis.policy.io.xml.PermisXmlReader;
 35  
 
 36  
 
 37  
 /**
 38  
  *
 39  
  * @since 0.3.0
 40  
  */
 41  
 public final class AttributeCertificateExtractorUtility {
 42  
 
 43  
         //---- Static
 44  
 
 45  
         /**
 46  
          * Reads a {@link TimePeriod} from an {@link AttributeCertificate}.
 47  
          * @param certificate an {@link AttributeCertificate}.
 48  
          * @return a {@link TimePeriod}.
 49  
          * @since 0.3.0
 50  
          */
 51  
         public static TimePeriod readValidityPeriod (AttributeCertificate certificate) {
 52  9
                 nullCheck(certificate);
 53  
 
 54  9
                 return new AbsoluteTimePeriod(
 55  
                         certificate.getNotBefore(),
 56  
                         certificate.getNotAfter()
 57  
                 );
 58  
         }
 59  
 
 60  
         /**
 61  
          * Reads a holder from an {@link AttributeCertificate}.
 62  
          * Currently only the entityName syntax is supported.
 63  
          * RFC 3281 allows three different (optional) holder syntaxes: baseCertificateID, entityName and
 64  
          * objectDigestInfo. The meaning is clear if exactly one holder is defined and it is not clear
 65  
          * if more than one are defined. Therefore FRC 3281 recommends to use only one.
 66  
          * @param certificate an {@link AttributeCertificate}.
 67  
          * @return an {@link X500Principal}.
 68  
          * @throws AttributeCertificateException indicates an holder reading problem.
 69  
          * @since 0.3.0
 70  
          */
 71  
         public static X500Principal readHolder (AttributeCertificate certificate)
 72  
                 throws AttributeCertificateException
 73  
         {
 74  9
                 nullCheck(certificate);
 75  
 
 76  9
                 final Principal[] principals = certificate.getHolder().getEntityNames();
 77  9
                 if (principals.length != 1) {
 78  0
                         throw new AttributeCertificateException(
 79  
                                 "AC should contain exactly one general holder name."
 80  
                         );
 81  
                 }
 82  9
                 if (!(principals[0] instanceof X500Principal)) {
 83  0
                         throw new AttributeCertificateException("AC contains an illeagal holder name.");
 84  
                 }
 85  
 
 86  9
                 return (X500Principal) principals[0];
 87  
         }
 88  
 
 89  
         /**
 90  
          * Reads a issuer from an {@link AttributeCertificate}.
 91  
          * RFC 3281 defines that exactly one general name must be specified.
 92  
          * @param certificate an {@link AttributeCertificate}.
 93  
          * @return an {@link X500Principal}.
 94  
          * @throws AttributeCertificateException indicates an issuer reading problem.
 95  
          * @since 0.3.0
 96  
          */
 97  
         public static X500Principal readIssuer (AttributeCertificate certificate)
 98  
                 throws AttributeCertificateException
 99  
         {
 100  8
                 nullCheck(certificate);
 101  
 
 102  8
                 final Principal[] principals = certificate.getIssuer().getPrincipals();
 103  8
                 if (principals.length != 1) {
 104  0
                         throw new AttributeCertificateException(
 105  
                                 "AC must contain exactly one general issuer name."
 106  
                         );
 107  
                 }
 108  8
                 if (!(principals[0] instanceof X500Principal)) {
 109  0
                         throw new AttributeCertificateException("AC contains an illeagal issuer name.");
 110  
                 }
 111  
 
 112  8
                 return (X500Principal) principals[0];
 113  
         }
 114  
 
 115  
         /**
 116  
          * Reads a policy from an {@link AttributeCertificate}.
 117  
          * @param certificate an {@link AttributeCertificate}.
 118  
          * @return the policy {@link String}.
 119  
          * @throws AttributeCertificateException indicates a reading problem.
 120  
          * @since 0.3.0
 121  
          */
 122  
         public static String readPolicyAttribute (AttributeCertificate certificate)
 123  
                 throws AttributeCertificateException
 124  
         {
 125  0
                 nullCheck(certificate);
 126  
 
 127  0
                 final X509Attribute[] attributes = certificate.getAttributes(PolicyAttribute.OID);
 128  0
                 if (attributes == null || attributes.length == 0) {
 129  0
                         throw new AttributeCertificateException("AC contains no policy attribute.");
 130  
                 }
 131  0
                 if (attributes.length > 1) {
 132  0
                         throw new AttributeCertificateException("AC contains more than one policy attribute.");
 133  
                 }
 134  
                 try {
 135  0
                         return new PolicyAttribute(attributes[0]).getPolicy();
 136  0
                 } catch (StreamParsingException e) {
 137  0
                         throw new AttributeCertificateException("AC contains invalid encoded policy.", e);
 138  
                 }
 139  
         }
 140  
 
 141  
         /**
 142  
          * Reads a {@link List} of roles from an {@link AttributeCertificate}.
 143  
          * @param certificate an {@link AttributeCertificate}.
 144  
          * @return the role {@link List}.
 145  
          * @throws AttributeCertificateException indicates a reading problem.
 146  
          * @since 0.3.0
 147  
          */
 148  
         public static List<RoleDefinition> readRoleAttribute (AttributeCertificate certificate)
 149  
                 throws AttributeCertificateException
 150  
         {
 151  9
                 nullCheck(certificate);
 152  
 
 153  9
                 final X509Attribute[] attributes = certificate.getAttributes(RoleAttribute.OID);
 154  9
                 if (attributes == null || attributes.length == 0) {
 155  0
                         throw new AttributeCertificateException("AC contains no role attribute.");
 156  
                 }
 157  9
                 if (attributes.length > 1) {
 158  0
                         throw new AttributeCertificateException("AC contains more than one role attribute.");
 159  
                 }
 160  
                 try {
 161  9
                         return new RoleAttribute(attributes[0]).getRoles();
 162  0
                 } catch (StreamParsingException e) {
 163  0
                         throw new AttributeCertificateException("AC contains invalid encoded roles.", e);
 164  
                 }
 165  
         }
 166  
 
 167  
         /**
 168  
          * Creates a policy decision point from the specified attribute certificate and verifies it
 169  
          * with the specified certificate verifier.
 170  
          *
 171  
          * @param policyCertificate The URL of the attribute certificate containing the policy.
 172  
          * @param certificateVerifier The certificate verifier used to verify the attribute certificate
 173  
          * containing the policy.
 174  
          * @return Returns the policy object.
 175  
          * @throws StreamParsingException Thrown if an attribute certificate cannot be parsed.
 176  
          * @throws IOException Thrown if the attribute certificate cannot be read.
 177  
          * @throws CertificateException Thrown if a certificate cannot be verified.
 178  
          * @throws PolicyException Thrown if the policy cannot be parsed.
 179  
          * @throws AttributeCertificateException  if the policy cannot be parsed.
 180  
          *
 181  
          * @since 0.3.0
 182  
          */
 183  
         public static PolicyDecisionPoint createPolicyDecisionPoint (
 184  
                 URL policyCertificate, CertificateVerifier certificateVerifier
 185  
         )
 186  
                 throws StreamParsingException,
 187  
                         IOException,
 188  
                         CertificateException,
 189  
                         PolicyException,
 190  
                         AttributeCertificateException
 191  
         {
 192  0
                 if (policyCertificate == null || certificateVerifier == null) {
 193  0
                         throw new IllegalArgumentException("Policy or certificate verifier is null");
 194  
                 }
 195  
 
 196  0
                 final AttributeCertificate certificate =
 197  
                         new AttributeCertificate(policyCertificate.openStream());
 198  
 
 199  0
                 final TimePeriod validity =
 200  
                         AttributeCertificateExtractorUtility.readValidityPeriod(certificate);
 201  
 
 202  
                 // Verify certificate.
 203  
                 try {
 204  0
                         certificateVerifier.verifyCertificate(certificate);
 205  0
                 } catch (Exception e) {
 206  0
                         throw new CertificateException("Could not verify policy attribute certifcate", e);
 207  0
                 }
 208  
 
 209  
                 // Get policy.
 210  0
                 final String policy = AttributeCertificateExtractorUtility.readPolicyAttribute(certificate);
 211  
 
 212  
                 // Create expirable policy.
 213  0
                 final PolicyReader reader = new StrictPolicyReader(
 214  
                         new PermisXmlReader(
 215  
                                 new StringReader(policy), new BasicPartBeanFactory()
 216  
                         )
 217  
                 );
 218  0
                 return new ExpirablePolicyDecisionPoint(reader.readPolicy(), validity);
 219  
         }
 220  
 
 221  
         /**
 222  
          * Extracts the policy as a string from the specified attribute certificate.
 223  
          *
 224  
          * @param policyCertificate The URL of the attribute certificate containing the policy.
 225  
          * @return Returns the policy as a string.
 226  
          * @throws IOException Thrown if the attribute certificate cannot be read.
 227  
          * @throws AttributeCertificateException  if the policy cannot be parsed.
 228  
          *
 229  
          * @since 0.3.0
 230  
          */
 231  
         public static String readPolicy (URL policyCertificate)
 232  
                 throws        IOException,
 233  
                                 AttributeCertificateException
 234  
         {
 235  0
                 return AttributeCertificateExtractorUtility.readPolicyAttribute(
 236  
                         new AttributeCertificate(policyCertificate.openStream()));
 237  
         }
 238  
 
 239  
         /**
 240  
          * @since 0.3.0
 241  
          */
 242  
         public static X500Principal toX500Principal (URI uri) {
 243  0
                 return new X500Principal(uri.getPath());
 244  
         }
 245  
 
 246  
         /**
 247  
          * @since 0.3.0
 248  
          */
 249  
         public static URI toUri (X500Principal principal) {
 250  16
                 return URI.create(principal.getName("CANONICAL"));
 251  
         }
 252  
 
 253  
         /**
 254  
          * @since 0.3.0
 255  
          */
 256  
         private static void nullCheck (AttributeCertificate certificate) {
 257  35
                 if (certificate == null) {
 258  0
                         throw new IllegalArgumentException("Attribute certificate is null.");
 259  
                 }
 260  35
         }
 261  
 
 262  
         //---- Constructor
 263  
 
 264  
         /**
 265  
          * @since 0.3.0
 266  
          */
 267  0
         private AttributeCertificateExtractorUtility () {
 268  
                 // Prevents instantiation.
 269  0
         }
 270  
 
 271  
 
 272  
 }