blob: 0719e4693b3850f4eaffc68e6d17cb8f5c88804d [file] [log] [blame]
J. Duke319a3b92007-12-01 00:00:00 +00001/*
2 * Portions Copyright 2000-2006 Sun Microsystems, Inc. All Rights Reserved.
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * This code is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License version 2 only, as
7 * published by the Free Software Foundation. Sun designates this
8 * particular file as subject to the "Classpath" exception as provided
9 * by Sun in the LICENSE file that accompanied this code.
10 *
11 * This code is distributed in the hope that it will be useful, but WITHOUT
12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14 * version 2 for more details (a copy is included in the LICENSE file that
15 * accompanied this code).
16 *
17 * You should have received a copy of the GNU General Public License version
18 * 2 along with this work; if not, write to the Free Software Foundation,
19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20 *
21 * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
22 * CA 95054 USA or visit www.sun.com if you need additional information or
23 * have any questions.
24 */
25
26/*
27 *
28 * (C) Copyright IBM Corp. 1999 All Rights Reserved.
29 * Copyright 1997 The Open Group Research Institute. All rights reserved.
30 */
31
32package sun.security.krb5.internal;
33
34import sun.security.krb5.Config;
35import sun.security.krb5.Asn1Exception;
36import sun.security.util.*;
37import java.net.InetAddress;
38import java.net.Inet4Address;
39import java.net.Inet6Address;
40import java.net.UnknownHostException;
41import java.io.IOException;
42
43/**
44 * Implements the ASN.1 HostAddress type.
45 *
46 * <xmp>
47 * HostAddress ::= SEQUENCE {
48 * addr-type [0] Int32,
49 * address [1] OCTET STRING
50 * }
51 * </xmp>
52 *
53 * <p>
54 * This definition reflects the Network Working Group RFC 4120
55 * specification available at
56 * <a href="http://www.ietf.org/rfc/rfc4120.txt">
57 * http://www.ietf.org/rfc/rfc4120.txt</a>.
58 */
59
60public class HostAddress implements Cloneable {
61 int addrType;
62 byte[] address = null;
63
64 private static InetAddress localInetAddress; //caches local inet address
65 private static final boolean DEBUG = sun.security.krb5.internal.Krb5.DEBUG;
66 private volatile int hashCode = 0;
67
68 private HostAddress(int dummy) {}
69
70 public Object clone() {
71 HostAddress new_hostAddress = new HostAddress(0);
72 new_hostAddress.addrType = addrType;
73 if (address != null) {
74 new_hostAddress.address = address.clone();
75 }
76 return new_hostAddress;
77 }
78
79
80 public int hashCode() {
81 if (hashCode == 0) {
82 int result = 17;
83 result = 37*result + addrType;
84 if (address != null) {
85 for (int i=0; i < address.length; i++) {
86 result = 37*result + address[i];
87 }
88 }
89 hashCode = result;
90 }
91 return hashCode;
92
93 }
94
95 public boolean equals(Object obj) {
96 if (this == obj) {
97 return true;
98 }
99
100 if (!(obj instanceof HostAddress)) {
101 return false;
102 }
103
104 HostAddress h = (HostAddress)obj;
105 if (addrType != h.addrType ||
106 (address != null && h.address == null) ||
107 (address == null && h.address != null))
108 return false;
109 if (address != null && h.address != null) {
110 if (address.length != h.address.length)
111 return false;
112 for (int i = 0; i < address.length; i++)
113 if (address[i] != h.address[i])
114 return false;
115 }
116 return true;
117 }
118
119 private static synchronized InetAddress getLocalInetAddress()
120 throws UnknownHostException {
121
122 if (localInetAddress == null) {
123 localInetAddress = InetAddress.getLocalHost();
124 }
125 if (localInetAddress == null) {
126 throw new UnknownHostException();
127 }
128 return (localInetAddress);
129 }
130
131 /**
132 * Gets the InetAddress of this HostAddress.
133 * @return the IP address for this specified host.
134 * @exception if no IP address for the host could be found.
135 *
136 */
137 public InetAddress getInetAddress() throws UnknownHostException {
138 // the type of internet addresses is 2.
139 if (addrType == Krb5.ADDRTYPE_INET ||
140 addrType == Krb5.ADDRTYPE_INET6) {
141 return (InetAddress.getByAddress(address));
142 } else {
143 // if it is other type (ISO address, XNS address, etc)
144 return null;
145 }
146 }
147
148 private int getAddrType(InetAddress inetAddress) {
149 int addressType = 0;
150 if (inetAddress instanceof Inet4Address)
151 addressType = Krb5.ADDRTYPE_INET;
152 else if (inetAddress instanceof Inet6Address)
153 addressType = Krb5.ADDRTYPE_INET6;
154 return (addressType);
155 }
156
157 // implicit default not in Config.java
158 public HostAddress() throws UnknownHostException {
159 InetAddress inetAddress = getLocalInetAddress();
160 addrType = getAddrType(inetAddress);
161 address = inetAddress.getAddress();
162 }
163
164 /**
165 * Creates a HostAddress from the specified address and address type.
166 *
167 * @param new_addrType the value of the address type which matches the defined
168 * address family constants in the Berkeley Standard
169 * Distributions of Unix.
170 * @param new_address network address.
171 * @exception KrbApErrException if address type and address length do not match defined value.
172 *
173 */
174 public HostAddress(int new_addrType, byte[] new_address)
175 throws KrbApErrException, UnknownHostException {
176 switch(new_addrType) {
177 case Krb5.ADDRTYPE_INET: //Internet address
178 if (new_address.length != 4)
179 throw new KrbApErrException(0, "Invalid Internet address");
180 break;
181 case Krb5.ADDRTYPE_CHAOS:
182 if (new_address.length != 2) //CHAOSnet address
183 throw new KrbApErrException(0, "Invalid CHAOSnet address");
184 break;
185 case Krb5.ADDRTYPE_ISO: // ISO address
186 break;
187 case Krb5.ADDRTYPE_IPX: // XNS address
188 if (new_address.length != 6)
189 throw new KrbApErrException(0, "Invalid XNS address");
190 break;
191 case Krb5.ADDRTYPE_APPLETALK: //AppleTalk DDP address
192 if (new_address.length != 3)
193 throw new KrbApErrException(0, "Invalid DDP address");
194 break;
195 case Krb5.ADDRTYPE_DECNET: //DECnet Phase IV address
196 if (new_address.length != 2)
197 throw new KrbApErrException(0, "Invalid DECnet Phase IV address");
198 break;
199 case Krb5.ADDRTYPE_INET6: //Internet IPv6 address
200 if (new_address.length != 16)
201 throw new KrbApErrException(0, "Invalid Internet IPv6 address");
202 break;
203 }
204
205 addrType = new_addrType;
206 if (new_address != null) {
207 address = new_address.clone();
208 }
209 if (DEBUG) {
210 if (addrType == Krb5.ADDRTYPE_INET ||
211 addrType == Krb5.ADDRTYPE_INET6) {
212 System.out.println("Host address is " +
213 InetAddress.getByAddress(address));
214 }
215 }
216 }
217
218 public HostAddress(InetAddress inetAddress) {
219 addrType = getAddrType(inetAddress);
220 address = inetAddress.getAddress();
221 }
222
223 /**
224 * Constructs a host address from a single DER-encoded value.
225 * @param encoding a single DER-encoded value.
226 * @exception Asn1Exception if an error occurs while decoding an ASN1 encoded data.
227 * @exception IOException if an I/O error occurs while reading encoded data.
228 *
229 */
230 public HostAddress(DerValue encoding) throws Asn1Exception, IOException {
231 DerValue der = encoding.getData().getDerValue();
232 if ((der.getTag() & (byte)0x1F) == (byte)0x00) {
233 addrType = der.getData().getBigInteger().intValue();
234 }
235 else
236 throw new Asn1Exception(Krb5.ASN1_BAD_ID);
237 der = encoding.getData().getDerValue();
238 if ((der.getTag() & (byte)0x1F) == (byte)0x01) {
239 address = der.getData().getOctetString();
240 }
241 else
242 throw new Asn1Exception(Krb5.ASN1_BAD_ID);
243 if (encoding.getData().available() > 0)
244 throw new Asn1Exception(Krb5.ASN1_BAD_ID);
245 }
246
247 /**
248 * Encodes a HostAddress object.
249 * @return a byte array of encoded HostAddress object.
250 * @exception Asn1Exception if an error occurs while decoding an ASN1 encoded data.
251 * @exception IOException if an I/O error occurs while reading encoded data.
252 *
253 */
254
255 public byte[] asn1Encode() throws Asn1Exception, IOException {
256 DerOutputStream bytes = new DerOutputStream();
257 DerOutputStream temp = new DerOutputStream();
258 temp.putInteger(this.addrType);
259 bytes.write(DerValue.createTag(DerValue.TAG_CONTEXT, true, (byte)0x00), temp);
260 temp = new DerOutputStream();
261 temp.putOctetString(address);
262 bytes.write(DerValue.createTag(DerValue.TAG_CONTEXT, true, (byte)0x01), temp);
263 temp = new DerOutputStream();
264 temp.write(DerValue.tag_Sequence, bytes);
265 return temp.toByteArray();
266 }
267
268 /**
269 * Parses (unmarshal) a host address from a DER input stream. This form
270 * parsing might be used when expanding a value which is part of
271 * a constructed sequence and uses explicitly tagged type.
272 *
273 * @exception Asn1Exception on error.
274 * @exception IOException if an I/O error occurs while reading encoded data.
275 * @param data the Der input stream value, which contains one or more marshaled value.
276 * @param explicitTag tag number.
277 * @param optional indicates if this data field is optional
278 * @return an instance of HostAddress.
279 *
280 */
281 public static HostAddress parse(DerInputStream data, byte explicitTag,
282 boolean optional)
283 throws Asn1Exception, IOException{
284 if ((optional) &&
285 (((byte)data.peekByte() & (byte)0x1F) != explicitTag)) {
286 return null;
287 }
288 DerValue der = data.getDerValue();
289 if (explicitTag != (der.getTag() & (byte)0x1F)) {
290 throw new Asn1Exception(Krb5.ASN1_BAD_ID);
291 }
292 else {
293 DerValue subDer = der.getData().getDerValue();
294 return new HostAddress(subDer);
295 }
296 }
297
298}