/*
* 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 java.io.IOException;
import org.bouncycastle.asn1.ASN1EncodableVector;
import org.bouncycastle.asn1.ASN1Integer;
import org.bouncycastle.asn1.ASN1Primitive;
import org.bouncycastle.asn1.ASN1Sequence;
import org.bouncycastle.asn1.ASN1TaggedObject;
import org.bouncycastle.asn1.BERTaggedObject;
import org.bouncycastle.asn1.DLSequence;
import eu.emi.security.authn.x509.proxy.BaseProxyCertificateOptions;
import eu.emi.security.authn.x509.proxy.ProxyPolicy;
/**
* Proxy cert info extension class.
*
* <pre>
* ProxyCertInfoExtension ::= SEQUENCE {
* proxyPolicy ProxyPolicy,
* pCPathLenConstraint [1] EXPLICIT ProxyCertPathLengthConstraint OPTIONAL }
*
* ProxyCertPathLengthConstraint ::= INTEGER
* </pre>
*
* @author Joni Hahkala
* @author K. Benedyczak
*/
public class DraftRFCProxyCertInfoExtension extends ProxyCertInfoExtension
{
/** The oid of the rfc draft proxy cert extension. */
public static final String DRAFT_EXTENSION_OID = "1.3.6.1.4.1.3536.1.222";
/**
* Generate new proxy certificate info extension with length limit len
* and policy policy. Use negative value if no limit is desired.
*
* @param pathLen
* the maximum number of proxy certificates to follow
* this one. If -1 is used then no limit will be set.
* @param policy
* the proxy policy extension.
*/
public DraftRFCProxyCertInfoExtension(int pathLen, ProxyPolicy policy)
{
this.pathLen = pathLen;
this.policy = policy;
}
/**
* Generate a proxy that inherits all rights and that has no cert path
* length limitations.
*/
public DraftRFCProxyCertInfoExtension()
{
policy = new ProxyPolicy(ProxyPolicy.INHERITALL_POLICY_OID);
}
/**
* Constructor that generates instance out of byte array.
*
* @param bytes
* The byte array to consider as the ASN.1 encoded
* proxyCertInfo extension.
* @throws IOException
* thrown in case the parsing of the byte array fails.
*/
public DraftRFCProxyCertInfoExtension(byte[] bytes) throws IOException
{
this((ASN1Sequence) ASN1Primitive.fromByteArray(bytes));
}
/**
* Read a proxyCertInfoExtension from the ASN1 sequence.
*
* @param seq
* The sequence containing the extension.
* @throws IOException IO exception
*/
public DraftRFCProxyCertInfoExtension(ASN1Sequence seq) throws IOException
{
int index = 0;
if (seq == null || seq.size() == 0)
throw new IOException("ProxyCertInfoExtension is empty");
if (seq.getObjectAt(index) instanceof DLSequence)
{
policy = new ProxyPolicy((DLSequence)seq.getObjectAt(index));
index++;
} else
{
throw new IOException("ProxyCertInfoExtension parser error, expected policy sequence, but got: "
+ seq.getObjectAt(index).getClass());
}
if (seq.size() <= index)
return;
if (seq.getObjectAt(index) instanceof ASN1TaggedObject)
{
ASN1TaggedObject tagged = (ASN1TaggedObject) seq.getObjectAt(index);
if (tagged.getTagNo() != 1)
throw new IOException("ProxyCertInfoExtension parser error, "
+ "expected path constraint tagged with 1 but was tagged with " +
tagged.getTagNo());
ASN1Primitive pathLenObj = tagged.getObject();
if (pathLenObj instanceof ASN1Integer)
pathLen = ((ASN1Integer) pathLenObj).getValue().intValue();
else
throw new IOException("ProxyCertInfoExtension parser error, "
+ "expected path constraint of integer type but got " +
pathLenObj);
} else
{
throw new IOException("ProxyCertInfoExtension parser error, "
+ "expected path constraint encoded as tagged integer but but got " +
seq.getObjectAt(index));
}
index++;
if (seq.size() > index)
throw new IOException("ProxyCertInfoExtension parser error, sequence contains too many items");
}
@Override
public ASN1Primitive toASN1Primitive()
{
ASN1EncodableVector v = new ASN1EncodableVector();
if (policy != null)
{
v.add(policy.toASN1Primitive());
} else
{
throw new IllegalArgumentException("Can't generate " +
"ProxyCertInfoExtension without mandatory policy");
}
if (pathLen != BaseProxyCertificateOptions.UNLIMITED_PROXY_LENGTH)
{
v.add(new BERTaggedObject(true, 1, new ASN1Integer(pathLen)));
}
return new DLSequence(v);
}
}