// --- 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 java.util.StringTokenizer;
import netscape.security.util.DerOutputStream;
import netscape.security.util.DerValue;
/**
* This class implements the IPAddressName as required by the GeneralNames
* ASN.1 object.
*
* @see GeneralName
* @see GeneralNameInterface
* @see GeneralNames
*
* @version 1.2
*
* @author Amit Kapoor
* @author Hemma Prafullchandra
*/
public class IPAddressName implements GeneralNameInterface {
/**
*
*/
private static final long serialVersionUID = -4240184399679453666L;
private byte[] address;
/**
* Create the IPAddressName object from the passed encoded Der value.
*
* @param derValue the encoded DER IPAddressName.
* @exception IOException on error.
*/
public IPAddressName(DerValue derValue) throws IOException {
address = derValue.getOctetString();
}
/**
* Create the IPAddressName object with the specified name.
*
* @param name the IPAddressName.
*/
public IPAddressName(byte[] address) {
this.address = address;
}
protected static final char IPv4_LEN = 4;
protected static final char IPv6_LEN = 16;
protected static final IPAddr IPv4 = new IPv4Addr();
protected static final IPAddr IPv6 = new IPv6Addr();
/**
* Create the IPAddressName object with a string representing the
* ip address and a string representing the netmask, with encoding
* having ip address encoding followed by the netmask encoding.
* This form is needed for name constraints extension.
*
* @param s the ip address in the format: n.n.n.n or x:x:x:x:x:x:x:x (RFC 1884)
* @param netmask the netmask address in the format: n.n.n.n or x:x:x:x:x:x:x:x (RFC 1884)
*/
public IPAddressName(String s, String netmask) {
// Based on PKIX RFC2459. IPAddress has
// 8 bytes (instead of 4 bytes) in the
// context of NameConstraints
IPAddr ipAddr = null;
if (s.indexOf(':') != -1) {
ipAddr = IPv6;
address = new byte[IPv6_LEN * 2];
} else {
ipAddr = IPv4;
address = new byte[IPv4_LEN * 2];
}
StringTokenizer st = new StringTokenizer(s, ",");
int numFilled = ipAddr.getIPAddr(st.nextToken(), address, 0);
if (st.hasMoreTokens()) {
ipAddr.getIPAddr(st.nextToken(), address, numFilled);
} else {
for (int i = numFilled; i < address.length; i++)
address[i] = (byte) 0xff;
}
}
/**
* Create the IPAddressName object with a string representing the
* ip address.
*
* @param s the ip address in the format: n.n.n.n or x:x:x:x:x:x:x:x
*/
public IPAddressName(String s) {
IPAddr ipAddr = null;
if (s.indexOf(':') != -1) {
ipAddr = IPv6;
address = new byte[IPv6_LEN];
} else {
ipAddr = IPv4;
address = new byte[IPv4_LEN];
}
ipAddr.getIPAddr(s, address, 0);
}
/**
* Return the type of the GeneralName.
*/
public int getType() {
return (GeneralNameInterface.NAME_IP);
}
/**
* Encode the IPAddress name into the DerOutputStream.
*
* @param out the DER stream to encode the IPAddressName to.
* @exception IOException on encoding errors.
*/
public void encode(DerOutputStream out) throws IOException {
out.putOctetString(address);
}
/**
* Return a printable string of IPaddress
*/
public String toString() {
if (address.length == 4) {
return ("IPAddress: " + (address[0] & 0xff) + "."
+ (address[1] & 0xff) + "."
+ (address[2] & 0xff) + "." + (address[3] & 0xff));
} else {
StringBuffer r = new StringBuffer("IPAddress: " + Integer.toHexString(address[0] & 0xff));
String hexString = Integer.toHexString(address[1] & 0xff);
if (hexString.length() == 1) {
r.append("0" + hexString);
} else {
r.append(hexString);
}
for (int i = 2; i < address.length;) {
r.append(":" + Integer.toHexString(address[i] & 0xff));
hexString = Integer.toHexString(address[i + 1] & 0xff);
if (hexString.length() == 1) {
r.append("0" + hexString);
} else {
r.append(hexString);
}
i += 2;
}
return r.toString();
}
}
}
interface IPAddr {
public int getIPAddr(String s, byte[] address, int start);
public int getLength();
}
class IPv4Addr implements IPAddr {
protected static final int IPv4_LEN = 4;
/**
* Gets an IP v4 address in the form n.n.n.n.
*/
public int getIPAddr(String s, byte[] address, int start) {
StringTokenizer st = new StringTokenizer(s, ".");
int nt = st.countTokens();
if (nt != IPv4_LEN)
throw new InvalidIPAddressException(s);
try {
int end = start + nt;
for (int i = start; i < end; i++) {
Integer j = new Integer(st.nextToken());
address[i] = (byte) j.intValue();
}
} catch (NumberFormatException e) {
throw new InvalidIPAddressException(s);
}
return nt;
}
public int getLength() {
return IPv4_LEN;
}
}
class IPv6Addr implements IPAddr {
/**
* Gets an IP address in the forms as defined in RFC1884:
*