// --- BEGIN COPYRIGHT BLOCK --- // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation; version 2 of the License. // // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License along // with this program; if not, write to the Free Software Foundation, Inc., // 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. // // (C) 2007 Red Hat, Inc. // All rights reserved. // --- END COPYRIGHT BLOCK --- package netscape.security.x509; import java.io.ByteArrayOutputStream; import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import netscape.security.util.BitArray; import netscape.security.util.DerOutputStream; import netscape.security.util.DerValue; import org.mozilla.jss.asn1.ANY; import org.mozilla.jss.asn1.ASN1Template; import org.mozilla.jss.asn1.ASN1Util; import org.mozilla.jss.asn1.ASN1Value; import org.mozilla.jss.asn1.BIT_STRING; import org.mozilla.jss.asn1.EXPLICIT; import org.mozilla.jss.asn1.InvalidBERException; import org.mozilla.jss.asn1.SEQUENCE; import org.mozilla.jss.asn1.Tag; /** *
* DistributionPoint ::= SEQUENCE { * distributionPoint [0] DistributionPointName OPTIONAL, * reasons [1] ReasonFlags OPTIONAL, * cRLIssuer [2] GeneralNames OPTIONAL } * * DistributionPointName ::= CHOICE { * fullName [0] GeneralNames, * nameRelativeToCRLIssuer [1] RelativeDistinguishedName } * * ReasonFlags ::= BIT STRING { * unused (0), * keyCompromise (1), * cACompromise (2), * affiliationChanged (3), * superseded (4), * cessationOfOperation (5), * certificateHold (6) } **/ public class CRLDistributionPoint implements ASN1Value { // at most one of the two following may be specified: private GeneralNames fullName; private RDN relativeName; // cache encoding of fullName private ANY fullNameEncoding; private BitArray reasons; // optional, may be null private GeneralNames CRLIssuer; // optional, may be null private ANY CRLIssuerEncoding; // default constructor does nothing. /** * Returns the
fullName
of the DistributionPointName
, which may be null
.
*/
public GeneralNames getFullName() {
return fullName;
}
/**
* Returns the relativeName
of the DistributionPointName
, which may be null
.
*/
public RDN getRelativeName() {
return relativeName;
}
/**
* Sets the fullName
of the DistributionPointName
. It may be set to null
.
* If it is set to a non-null value, relativeName
will be
* set to null
, because at most one of these two attributes
* can be specified at a time.
*
* @exception GeneralNamesException If an error occurs encoding the
* name.
*/
public void setFullName(GeneralNames fullName)
throws GeneralNamesException, IOException {
this.fullName = fullName;
if (fullName != null) {
// encode the name to catch any problems with it
DerOutputStream derOut = new DerOutputStream();
fullName.encode(derOut);
try {
ANY raw = new ANY(derOut.toByteArray());
ByteArrayOutputStream bos = new ByteArrayOutputStream();
raw.encodeWithAlternateTag(Tag.get(0), bos);
fullNameEncoding = new ANY(bos.toByteArray());
} catch (InvalidBERException e) {
// assume this won't happen, since it would imply a bug
// in DerOutputStream
throw new GeneralNamesException(e.toString());
}
this.relativeName = null;
}
}
/**
* Sets the relativeName
of the DistributionPointName
. It may be set to null
.
* If it is set to a non-null value, fullName
will be
* set to null
, because at most one of these two attributes
* can be specified at a time.
*/
public void setRelativeName(RDN relativeName) {
this.relativeName = relativeName;
if (relativeName != null) {
this.fullName = null;
}
}
/**
* Returns the reason flags for this distribution point. May be null
.
*/
public BitArray getReasons() {
return reasons;
}
/**
* Sets the reason flags for this distribution point. May be set to null
.
*/
public void setReasons(BitArray reasons) {
this.reasons = reasons;
}
/**
* Returns the CRLIssuer for the CRL at this distribution point.
* May be null
.
*/
public GeneralNames getCRLIssuer() {
return CRLIssuer;
}
/**
* Sets the CRLIssuer for the CRL at this distribution point.
* May be set to null
.
*
* @exception GeneralNamesException If an error occurs encoding the name.
*/
public void setCRLIssuer(GeneralNames CRLIssuer)
throws GeneralNamesException, IOException {
this.CRLIssuer = CRLIssuer;
if (CRLIssuer != null) {
// encode the name to catch any problems with it
DerOutputStream derOut = new DerOutputStream();
CRLIssuer.encode(derOut);
try {
ANY raw = new ANY(derOut.toByteArray());
ByteArrayOutputStream bos = new ByteArrayOutputStream();
raw.encodeWithAlternateTag(Tag.get(2), bos);
CRLIssuerEncoding = new ANY(bos.toByteArray());
} catch (InvalidBERException e) {
throw new GeneralNamesException(e.toString());
}
}
}
/////////////////////////////////////////////////////////////
// DER encoding
/////////////////////////////////////////////////////////////
private static final Tag TAG = SEQUENCE.TAG;
public Tag getTag() {
return TAG;
}
public void encode(OutputStream ostream) throws IOException {
encode(TAG, ostream);
}
public void encode(Tag implicitTag, OutputStream ostream)
throws IOException {
SEQUENCE seq = new SEQUENCE();
DerOutputStream derOut;
try {
// Encodes the DistributionPointName. Because DistributionPointName
// is a CHOICE, the [0] tag is forced to be EXPLICIT.
if (fullName != null) {
EXPLICIT distPoint = new EXPLICIT(Tag.get(0), fullNameEncoding);
seq.addElement(distPoint);
} else if (relativeName != null) {
derOut = new DerOutputStream();
relativeName.encode(derOut);
ANY rn = new ANY(derOut.toByteArray());
EXPLICIT raw = new EXPLICIT(Tag.get(1), rn);
ByteArrayOutputStream bos = new ByteArrayOutputStream();
raw.encode(bos);
ANY distPointName = new ANY(bos.toByteArray());
EXPLICIT distPoint = new EXPLICIT(Tag.get(0), distPointName);
seq.addElement(distPoint);
}
// Encodes the ReasonFlags.
if (reasons != null) {
derOut = new DerOutputStream();
derOut.putUnalignedBitString(reasons);
ANY raw = new ANY(derOut.toByteArray());
ByteArrayOutputStream bos = new ByteArrayOutputStream();
raw.encodeWithAlternateTag(Tag.get(1), bos);
ANY reasonEncoding = new ANY(bos.toByteArray());
seq.addElement(Tag.get(1), reasonEncoding);
}
// Encodes the CRLIssuer
if (CRLIssuer != null) {
seq.addElement(Tag.get(2), CRLIssuerEncoding);
}
seq.encode(implicitTag, ostream);
} catch (InvalidBERException e) {
// this shouldn't happen unless there is a bug in one of
// the Sun encoding classes
throw new IOException(e.toString());
}
}
// Template singleton
private static Template templateInstance = new Template();
/**
* Returns an instance of a template for decoding a CRLDistributionPoint.
*/
public static Template getTemplate() {
return templateInstance;
}
public static void main(String args[]) {
try {
if (args.length != 1) {
System.out.println("Usage: CRLDistributionPoint