/*
* Copyright (c) 2011-2012 ICM Uniwersytet Warszawski All rights reserved.
* See LICENCE file for licensing information.
*
* Derived from the code copyrighted and licensed as follows:
*
* Copyright (c) Members of the EGEE Collaboration. 2004.
* 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 eu.emi.security.authn.x509.helpers.proxy;
import static eu.emi.security.authn.x509.helpers.proxy.DraftRFCProxyCertInfoExtension.DRAFT_EXTENSION_OID;
import static eu.emi.security.authn.x509.helpers.proxy.RFCProxyCertInfoExtension.RFC_EXTENSION_OID;
import java.io.IOException;
import java.security.cert.X509Certificate;
import javax.security.auth.x500.X500Principal;
import org.bouncycastle.asn1.x500.AttributeTypeAndValue;
import org.bouncycastle.asn1.x500.RDN;
import org.bouncycastle.asn1.x500.X500Name;
import org.bouncycastle.asn1.x500.style.BCStyle;
import org.bouncycastle.asn1.x500.style.IETFUtils;
import eu.emi.security.authn.x509.helpers.CertificateHelpers;
import eu.emi.security.authn.x509.proxy.ProxyPolicy;
/**
* Various helpers for handling proxy certificates
*
* @author J. Hahkala
* @author K. Benedyczak
*/
public class ProxyHelper
{
/**
* Checks if the certificate is a proxy and if so return its type.
* @param certificate to be checked
* @return the proxy type or info that it is a normal certificate.
*/
public static ExtendedProxyType getProxyType(X509Certificate certificate)
{
if (certificate.getExtensionValue(RFC_EXTENSION_OID) != null
&& certificate.getExtensionValue(RFC_EXTENSION_OID).length > 0)
return ExtendedProxyType.RFC3820;
if (certificate.getExtensionValue(DRAFT_EXTENSION_OID) != null
&& certificate.getExtensionValue(DRAFT_EXTENSION_OID).length > 0)
return ExtendedProxyType.DRAFT_RFC;
String value;
try
{
value = getLastCN(certificate.getSubjectX500Principal());
} catch (IllegalArgumentException e) //empty subject DN
{
value = "";
}
if ("proxy".equals(value.toLowerCase())
|| "limited proxy".equals(value.toLowerCase()))
return ExtendedProxyType.LEGACY;
return ExtendedProxyType.NOT_A_PROXY;
}
public static String getLastCN(X500Principal principal) throws IllegalArgumentException
{
X500Name x500Name = CertificateHelpers.toX500Name(principal);
return getLastCN(x500Name);
}
public static String getLastCN(X500Name x500Name) throws IllegalArgumentException
{
RDN[] rdns = x500Name.getRDNs();
if (rdns.length == 0)
throw new IllegalArgumentException("The DN is empty");
RDN last = rdns[rdns.length-1];
if (last.isMultiValued())
throw new IllegalArgumentException("The DN is ended with a multivalued RDN");
AttributeTypeAndValue cn = last.getFirst();
if (!cn.getType().equals(BCStyle.CN))
throw new IllegalArgumentException("The DN is not ended with a CN AVA");
return IETFUtils.valueToString(cn.getValue());
}
/**
* Returns the proxy path limit of the proxy. The argument is not checked if
* is a real proxy.
* @param cert certificate
* @return path limit as set for the DRAFT and RFC proxies. In case of legacy proxies
* or unlimited proxies Integer.MAX_VALUE is returned.
* @throws IOException if the extension can not be parsed
*/
public static int getProxyPathLimit(X509Certificate cert)
throws IOException
{
ProxyCertInfoExtension info = ProxyCertInfoExtension.getInstance(cert);
if (info == null)
return Integer.MAX_VALUE;
return info.getProxyPathLimit();
}
/**
* Checks if the certificate is a limited proxy in Globus sense, i.e. if its last CN is equal to 'limited proxy'
* (in case of legacy proxies) or if the special limited proxy policy is used.
* @param cert certificate
* @return true only if the parameter is a limited proxy
* @throws IOException IO exception
*/
public static boolean isLimited(X509Certificate cert) throws IOException
{
ExtendedProxyType type = getProxyType(cert);
if (type == ExtendedProxyType.RFC3820 || type == ExtendedProxyType.DRAFT_RFC)
{
ProxyCertInfoExtension ext = ProxyCertInfoExtension.getInstance(cert);
ProxyPolicy policy = ext.getPolicy();
return ProxyPolicy.LIMITED_PROXY_OID.equals(policy.getPolicyOID());
} else if (type == ExtendedProxyType.LEGACY)
{
String cn;
try
{
cn = getLastCN(cert.getSubjectX500Principal());
} catch (IllegalArgumentException e)
{
cn = "";
}
return "limited proxy".equals(cn.toLowerCase());
}
return false;
}
}