// --- 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.IOException; import netscape.security.util.DerOutputStream; import netscape.security.util.DerValue; /** * This class implements the ASN.1 GeneralName object class. *
* The ASN.1 syntax for this is: * *
* GeneralName ::= CHOICE {
* otherName [0] OtherName,
* rfc822Name [1] IA5String,
* dNSName [2] IA5String,
* x400Address [3] ORAddress,
* directoryName [4] Name,
* ediPartyName [5] EDIPartyName,
* uniformResourceIdentifier [6] IA5String,
* iPAddress [7] OCTET STRING,
* registeredID [8] OBJECT IDENTIFIER
* }
*
*
* @author Amit Kapoor
* @author Hemma Prafullchandra
* @version 1.7
*/
public class GeneralName implements GeneralNameInterface {
/**
*
*/
private static final long serialVersionUID = 2244101501095555042L;
// Private data members
private GeneralNameInterface name = null;
/**
* Default constructor for the class.
*
* @param name the selected CHOICE from the list.
*/
public GeneralName(GeneralNameInterface name) {
this.name = name;
}
/**
* Create the object from its DER encoded value.
*
* @param encName the DER encoded GeneralName.
*/
public GeneralName(DerValue encName) throws IOException {
short tag = (byte) (encName.tag & 0x1f);
// NB. this is always encoded with the IMPLICIT tag
// The checks only make sense if we assume implicit tagging,
// with explicit tagging the form is always constructed.
switch (tag) {
case GeneralNameInterface.NAME_RFC822:
if (encName.isContextSpecific() && !encName.isConstructed()) {
encName.resetTag(DerValue.tag_IA5String);
name = new RFC822Name(encName);
} else
throw new IOException("Invalid encoding of RFC822 name");
break;
case GeneralNameInterface.NAME_DNS:
if (encName.isContextSpecific() && !encName.isConstructed()) {
encName.resetTag(DerValue.tag_IA5String);
name = new DNSName(encName);
} else
throw new IOException("Invalid encoding of DNS name");
break;
case GeneralNameInterface.NAME_URI:
if (encName.isContextSpecific() && !encName.isConstructed()) {
encName.resetTag(DerValue.tag_IA5String);
name = new URIName(encName);
} else
throw new IOException("Invalid encoding of URI");
break;
case GeneralNameInterface.NAME_IP:
if (encName.isContextSpecific() && !encName.isConstructed()) {
encName.resetTag(DerValue.tag_OctetString);
name = new IPAddressName(encName);
} else
throw new IOException("Invalid encoding of IP address");
break;
case GeneralNameInterface.NAME_ANY:
if (encName.isContextSpecific() && encName.isConstructed()) {
encName.resetTag(DerValue.tag_OctetString);
name = new OtherName(encName);
} else
throw new IOException("Invalid encoding of other name");
break;
case GeneralNameInterface.NAME_OID:
if (encName.isContextSpecific() && !encName.isConstructed()) {
encName.resetTag(DerValue.tag_ObjectId);
name = new OIDName(encName);
} else
throw new IOException("Invalid encoding of OID name");
break;
case GeneralNameInterface.NAME_DIRECTORY:
if (encName.isContextSpecific() && encName.isConstructed()) {
// Unlike the other cases, DirectoryName is EXPLICITly
// tagged, because the X.500 Name type is a CHOICE.
// Therefore, the sequence is actually nested in the
// content of this value. We'll pretend it's an octet
// string so we can get at the content bytes.
encName.resetTag(DerValue.tag_OctetString);
byte[] content = encName.getOctetString();
name = new X500Name(content);
} else
throw new IOException("Invalid encoding of Directory name");
break;
case GeneralNameInterface.NAME_EDI:
if (encName.isContextSpecific() && encName.isConstructed()) {
encName.resetTag(DerValue.tag_Sequence);
name = new EDIPartyName(encName);
} else
throw new IOException("Invalid encoding of EDI name");
break;
default:
throw new IOException("Unrecognized GeneralName tag, ("
+ tag + ")");
}
}
/**
* Return the type of the general name.
*/
public int getType() {
return (name.getType());
}
/**
* Return the name as user readable string
*/
public String toString() {
return (name.toString());
}
/**
* Encode the name to the specified DerOutputStream.
*
* @param out the DerOutputStream to encode the the GeneralName to.
* @exception IOException on encoding errors.
*/
public void encode(DerOutputStream out) throws IOException {
DerOutputStream tmp = new DerOutputStream();
name.encode(tmp);
int nameType = name.getType();
boolean constructedForm;
if (nameType == GeneralNameInterface.NAME_ANY ||
nameType == GeneralNameInterface.NAME_X400 ||
nameType == GeneralNameInterface.NAME_DIRECTORY ||
nameType == GeneralNameInterface.NAME_EDI) {
constructedForm = true;
} else {
constructedForm = false;
}
if (nameType == GeneralNameInterface.NAME_DIRECTORY) {
// EXPLICIT tag, because Name is a CHOICE type
out.write(DerValue.createTag(DerValue.TAG_CONTEXT,
constructedForm, (byte) nameType), tmp);
} else {
// IMPLICIT tag, the default
out.writeImplicit(DerValue.createTag(DerValue.TAG_CONTEXT,
constructedForm, (byte) nameType), tmp);
}
}
/**
* Unwrap this GeneralName until we reach something that is not
* a GeneralName.
*/
public GeneralNameInterface unwrap() {
if (this == name)
return null; // can't happen, but just in case...
if (name instanceof GeneralName)
return ((GeneralName) name).unwrap();
else
return name;
}
}