/* * Copyright (c) Members of the EGEE Collaboration. 2006-2010. * See http://www.eu-egee.org/partners/ for details on the copyright holders. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.glite.authz.pep.pip.provider; import java.security.cert.X509Certificate; import java.util.Collection; import java.util.HashSet; import java.util.List; import org.glite.authz.common.config.ConfigurationException; import org.glite.authz.common.model.Attribute; import org.glite.authz.common.model.Request; import org.glite.authz.common.model.Subject; import org.glite.authz.pep.pip.PIPProcessingException; import org.glite.voms.FQAN; import org.glite.voms.PKIStore; import org.glite.voms.PKIUtils; import org.glite.voms.VOMSAttribute; import org.slf4j.Logger; import org.slf4j.LoggerFactory; /** * A policy information point that extracts information from a X.509, version 3, certificate. The certificate may * include VOMS attribute certificates. All extract information is added to the subject(s) containing a valid * certificate chain. * * The PEM encoded end entity certificate, and its certificate chain, are expected to be bound to the subject attribute * {@value #X509_CERT_CHAIN_ID}. Only one end-entity certificate may be present in the chain. If the end entity * certificate contains a VOMS attribute certificate, and VOMS certificate validation is enabled, information from that * attribute certificate will also be added to the subject. Only one VOMS attribute certificate may be present in the * end-entity certificate. * * @see <a href="https://twiki.cnaf.infn.it/cgi-bin/twiki/view/VOMS">VOMS website</a> * @deprecated Legacy profile, do not use it. */ public class SCASLegacyPIP extends AbstractX509PIP { /** * The ID of the subject attribute, {@value} , containing the end-entity certificate's issuer's DN in the * non-standard OpenSSL format. */ public static final String SUBJECT_X509_ID = "http://authz-interop.org/xacml/subject/subject-x509-id"; /** The ID of the subject attribute, {@value} , containing the end-entity certificate's issuer's DN. */ public static final String X509_DN_ISSUER = "http://authz-interop.org/xacml/subject/subject-x509-issuer"; /** The ID of the subject attribute, {@value} , containing the VO given in the VOMS attribute certificate. */ public static final String VOMS_VO = "http://authz-interop.org/xacml/subject/vo"; /** * The ID of the subject attribute, {@value} , containing the DN of the VOMS service that signed the VOMS attribute * certificate. */ public static final String VOMS_SIGNER = "http://authz-interop.org/xacml/subject/voms-signing-subject"; /** The ID of the subject attribute, {@value} , containing the DN of the signer of the VOMS service's certificate. */ public static final String VOMS_SIGNER_ISSUER = "http://authz-interop.org/xacml/subject/voms-signing-issuer"; /** The ID of the subject attribute, {@value} , containing the FQANs given in the VOMS attribute certificate. */ public static final String VOMS_FQAN = "http://authz-interop.org/xacml/subject/voms-fqan"; /** The ID of the subject attribute, {@value} , containing the primary FQAN given in the VOMS attribute certificate. */ public static final String VOMS_PRIMARY_FQAN = "http://authz-interop.org/xacml/subject/voms-primary-fqan"; /** The ID of the subject attribute, {@value} , containing the end-entity certificate's serial number. */ public static final String X509_SN = "http://authz-interop.org/xacml/subject/certificate-serial-number"; /** The ID of the subject attribute, {@value} , containing the end-entity certificate's serial number. */ public static final String X509_CA_SN = "http://authz-interop.org/xacml/subject/ca-serial-number"; /** The ID of the subject attribute, {@value} , containing the VOMS server hostname and port. */ public static final String VOMS_DNS_PORT = "http://authz-interop.org/xacml/subject/voms-dns-port"; /** The ID of the subject attribute, {@value} , containing the end entity certificate CA policy OID. */ public static final String CA_POLICY_OID = "http://authz-interop.org/xacml/subject/ca-policy-oid"; /** The ID of the subject attribute, {@value} , containing the end-entity certificate processed by the PIP. */ public static final String X509_CERT_CHAIN_ID = "http://authz-interop.org/xacml/subject/cert-chain"; /** * The ID of the subject attribute, {@value} , containing the generic attributes given in the VOMS attribute * certificate. */ public static final String VOMS_GA = "http://authz-interop.org/xacml/subject/generic-attribute"; /** Class logger. */ private Logger log = LoggerFactory.getLogger(SCASLegacyPIP.class); /** * The constructor for this PIP. This constructor enables support for the VOMS attribute certificates. * * @param pipID ID of this PIP * @param requireProxy whether a subject's certificate chain must require a proxy in order to be valid * @param eeTrustMaterial trust material used to validate the subject's end entity certificate * @param acTrustMaterial trust material used to validate the subject's attribute certificate certificate, may be * null of AC support is not desired * * @throws ConfigurationException thrown if the configuration of the PIP fails */ public SCASLegacyPIP(String pipID, boolean requireProxy, PKIStore eeTrustMaterial, PKIStore acTrustMaterial) throws ConfigurationException { super(pipID, requireProxy, eeTrustMaterial, acTrustMaterial); } /** {@inheritDoc} */ protected String getCertificateAttributeId() { return X509_CERT_CHAIN_ID; } /** {@inheritDoc} */ protected String getCertificateAttributeDatatype() { return Attribute.DT_BASE64_BINARY; } /** {@inheritDoc} */ protected boolean appliesToRequest(Request request) { for (Subject subject : request.getSubjects()) { for (Attribute attrib : subject.getAttributes()) { if (X509_CERT_CHAIN_ID.equals(attrib.getId())) { return true; } } } return false; } /** * Processes one certificate chain and adds the information to the subjects in the request. * * @param endEntityCertificate end entity certificate for the subject currently being processed * @param certChain the certificate chain containing the end entity certificate from which information will be * extracted * * @return the attribute extracted from the certificate chain * * @throws PIPProcessingException thrown if there is a problem reading the information from the certificate chain */ protected Collection<Attribute> processCertChain(X509Certificate endEntityCertificate, X509Certificate[] certChain) throws PIPProcessingException { if (endEntityCertificate == null || certChain == null || certChain.length == 0) { return null; } X509Certificate caCert = null; for (X509Certificate cert : certChain) { if (cert.getSubjectX500Principal().equals(endEntityCertificate.getIssuerX500Principal())) { caCert = cert; } } if (caCert == null) { throw new PIPProcessingException("CA for the end entity certificate was not found in the cert chain"); } log.debug("Extracting end-entity certificate attributes"); HashSet<Attribute> subjectAttributes = new HashSet<Attribute>(); // subject X509 ID Attribute attribute = new Attribute(); attribute.setId(SUBJECT_X509_ID); attribute.setDataType(Attribute.DT_STRING); attribute.getValues().add(PKIUtils.getOpenSSLFormatPrincipal(endEntityCertificate.getSubjectX500Principal())); log.debug("Extracted attribute: {}", attribute); subjectAttributes.add(attribute); // X509 issuer attribute = new Attribute(); attribute.setId(X509_DN_ISSUER); attribute.setDataType(Attribute.DT_STRING); attribute.getValues().add(PKIUtils.getOpenSSLFormatPrincipal(endEntityCertificate.getIssuerX500Principal())); log.debug("Extracted attribute: {}", attribute); subjectAttributes.add(attribute); // cert serial number attribute = new Attribute(); attribute.setId(X509_SN); attribute.setDataType(Attribute.DT_INTEGER); attribute.getValues().add(endEntityCertificate.getSerialNumber().toString()); log.debug("Extracted attribute: {}", attribute); subjectAttributes.add(attribute); // CA cert serial number attribute = new Attribute(); attribute.setId(X509_CA_SN); attribute.setDataType(Attribute.DT_INTEGER); attribute.getValues().add(caCert.getSerialNumber().toString()); log.debug("Extracted attribute: {}", attribute); subjectAttributes.add(attribute); if (isVOMSSupportEnabled()) { Collection<Attribute> vomsAttributes = processVOMS(endEntityCertificate, certChain); if (vomsAttributes != null) { subjectAttributes.addAll(vomsAttributes); } } return subjectAttributes; } /** * Processes the VOMS attributes and puts valid attributes into the subject object. * * @param endEntityCert the end entity certificate for the subject being processed * @param certChain certificate chain containing the end entity certificate that contains the VOMS attribute * certificate * * @return the attributes extracted from the VOMS attribute certificate * * @throws PIPProcessingException thrown if the end entity certificate contains more than one attribute certificate */ @SuppressWarnings("unchecked") private Collection<Attribute> processVOMS(X509Certificate endEntityCert, X509Certificate[] certChain) throws PIPProcessingException { log.debug("Extracting VOMS attribute certificate attributes"); VOMSAttribute attributeCertificate = extractAttributeCertificate(certChain); if (attributeCertificate == null) { return null; } HashSet<Attribute> vomsAttributes = new HashSet<Attribute>(); // vo Attribute attribute = new Attribute(); attribute.setId(VOMS_VO); attribute.setDataType(Attribute.DT_STRING); attribute.getValues().add(attributeCertificate.getVO()); log.debug("Extracted attribute: {}", attribute); vomsAttributes.add(attribute); // voms signing subject attribute = new Attribute(); attribute.setId(VOMS_SIGNER); attribute.setDataType(Attribute.DT_STRING); attribute.getValues().add(attributeCertificate.getIssuer()); vomsAttributes.add(attribute); // voms signing issuer X509Certificate vomsServerIssuer = (X509Certificate)(attributeCertificate.getCertList().getCerts().get(1)); attribute = new Attribute(); attribute.setId(VOMS_SIGNER_ISSUER); attribute.setDataType(Attribute.DT_STRING); attribute.getValues().add(PKIUtils.getOpenSSLFormatPrincipal(vomsServerIssuer.getSubjectX500Principal())); vomsAttributes.add(attribute); // Primary and secondary FQANs List<FQAN> fqans = attributeCertificate.getListOfFQAN(); if (fqans != null && !fqans.isEmpty()) { Attribute primaryFqanAttribute = new Attribute(); primaryFqanAttribute.setId(VOMS_PRIMARY_FQAN); primaryFqanAttribute.setDataType(Attribute.DT_STRING); primaryFqanAttribute.getValues().add(fqans.get(0).getFQAN()); log.debug("Extracted attribute: {}", primaryFqanAttribute); vomsAttributes.add(primaryFqanAttribute); // handle rest of the fqans Attribute fqanAttribute = new Attribute(); fqanAttribute.setId(VOMS_FQAN); fqanAttribute.setDataType(Attribute.DT_STRING); for (FQAN fqan : fqans) { fqanAttribute.getValues().add(fqan.getFQAN()); } log.debug("Extracted attribute: {}", fqanAttribute); vomsAttributes.add(fqanAttribute); } // VOMS DNS and Port attribute = new Attribute(); attribute.setId(VOMS_DNS_PORT); attribute.setDataType(Attribute.DT_STRING); attribute.getValues().add(attributeCertificate.getHostPort()); vomsAttributes.add(attribute); return vomsAttributes; } }