src/java.security.jgss/share/classes/sun/security/krb5/internal/HostAddress.java
changeset 47216 71c04702a3d5
parent 32013 e7ad0380f7be
child 58331 e4ce29f6094e
equal deleted inserted replaced
47215:4ebc2e2fb97c 47216:71c04702a3d5
       
     1 /*
       
     2  * Copyright (c) 2000, 2006, Oracle and/or its affiliates. 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.  Oracle designates this
       
     8  * particular file as subject to the "Classpath" exception as provided
       
     9  * by Oracle 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
       
    22  * or visit www.oracle.com if you need additional information or have any
       
    23  * 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 
       
    32 package sun.security.krb5.internal;
       
    33 
       
    34 import sun.security.krb5.Config;
       
    35 import sun.security.krb5.Asn1Exception;
       
    36 import sun.security.util.*;
       
    37 import java.net.InetAddress;
       
    38 import java.net.Inet4Address;
       
    39 import java.net.Inet6Address;
       
    40 import java.net.UnknownHostException;
       
    41 import java.io.IOException;
       
    42 import java.util.Arrays;
       
    43 
       
    44 /**
       
    45  * Implements the ASN.1 HostAddress type.
       
    46  *
       
    47  * <pre>{@code
       
    48  * HostAddress     ::= SEQUENCE  {
       
    49  *         addr-type       [0] Int32,
       
    50  *         address         [1] OCTET STRING
       
    51  * }
       
    52  * }</pre>
       
    53  *
       
    54  * <p>
       
    55  * This definition reflects the Network Working Group RFC 4120
       
    56  * specification available at
       
    57  * <a href="http://www.ietf.org/rfc/rfc4120.txt">
       
    58  * http://www.ietf.org/rfc/rfc4120.txt</a>.
       
    59  */
       
    60 
       
    61 public class HostAddress implements Cloneable {
       
    62     int addrType;
       
    63     byte[] address = null;
       
    64 
       
    65     private static InetAddress localInetAddress; //caches local inet address
       
    66     private static final boolean DEBUG = sun.security.krb5.internal.Krb5.DEBUG;
       
    67     private volatile int hashCode = 0;
       
    68 
       
    69     private HostAddress(int dummy) {}
       
    70 
       
    71     public Object clone() {
       
    72         HostAddress new_hostAddress = new HostAddress(0);
       
    73         new_hostAddress.addrType = addrType;
       
    74         if (address != null) {
       
    75             new_hostAddress.address = address.clone();
       
    76         }
       
    77         return new_hostAddress;
       
    78     }
       
    79 
       
    80 
       
    81     public int hashCode() {
       
    82         if (hashCode == 0) {
       
    83             int result = 17;
       
    84             result = 37*result + addrType;
       
    85             if (address != null) {
       
    86                 for (int i=0; i < address.length; i++)  {
       
    87                     result = 37*result + address[i];
       
    88                 }
       
    89             }
       
    90             hashCode = result;
       
    91         }
       
    92         return hashCode;
       
    93 
       
    94     }
       
    95 
       
    96     public boolean equals(Object obj) {
       
    97         if (this == obj) {
       
    98             return true;
       
    99         }
       
   100 
       
   101         if (!(obj instanceof HostAddress)) {
       
   102             return false;
       
   103         }
       
   104 
       
   105         HostAddress h = (HostAddress)obj;
       
   106         if (addrType != h.addrType ||
       
   107             (address != null && h.address == null) ||
       
   108             (address == null && h.address != null))
       
   109             return false;
       
   110         if (address != null && h.address != null) {
       
   111             if (address.length != h.address.length)
       
   112                 return false;
       
   113             for (int i = 0; i < address.length; i++)
       
   114                 if (address[i] != h.address[i])
       
   115                     return false;
       
   116         }
       
   117         return true;
       
   118     }
       
   119 
       
   120     private static synchronized InetAddress getLocalInetAddress()
       
   121         throws UnknownHostException {
       
   122 
       
   123         if (localInetAddress == null) {
       
   124            localInetAddress = InetAddress.getLocalHost();
       
   125         }
       
   126         if (localInetAddress == null) {
       
   127             throw new UnknownHostException();
       
   128         }
       
   129         return (localInetAddress);
       
   130     }
       
   131 
       
   132     /**
       
   133      * Gets the InetAddress of this HostAddress.
       
   134      * @return the IP address for this specified host.
       
   135      * @exception UnknownHostException if no IP address for the host could be found.
       
   136      *
       
   137      */
       
   138     public InetAddress getInetAddress() throws UnknownHostException {
       
   139         // the type of internet addresses is 2.
       
   140         if (addrType == Krb5.ADDRTYPE_INET ||
       
   141             addrType == Krb5.ADDRTYPE_INET6) {
       
   142             return (InetAddress.getByAddress(address));
       
   143         } else {
       
   144             // if it is other type (ISO address, XNS address, etc)
       
   145             return null;
       
   146         }
       
   147     }
       
   148 
       
   149     private int getAddrType(InetAddress inetAddress) {
       
   150         int addressType = 0;
       
   151         if (inetAddress instanceof Inet4Address)
       
   152             addressType = Krb5.ADDRTYPE_INET;
       
   153         else if (inetAddress instanceof Inet6Address)
       
   154             addressType = Krb5.ADDRTYPE_INET6;
       
   155         return (addressType);
       
   156     }
       
   157 
       
   158     // implicit default not in Config.java
       
   159     public HostAddress() throws UnknownHostException {
       
   160         InetAddress inetAddress = getLocalInetAddress();
       
   161         addrType = getAddrType(inetAddress);
       
   162         address = inetAddress.getAddress();
       
   163     }
       
   164 
       
   165     /**
       
   166      * Creates a HostAddress from the specified address and address type.
       
   167      *
       
   168      * @param new_addrType the value of the address type which matches the defined
       
   169      *                       address family constants in the Berkeley Standard
       
   170      *                       Distributions of Unix.
       
   171      * @param new_address network address.
       
   172      * @exception KrbApErrException if address type and address length do not match defined value.
       
   173      *
       
   174      */
       
   175     public HostAddress(int new_addrType, byte[] new_address)
       
   176         throws KrbApErrException, UnknownHostException {
       
   177         switch(new_addrType) {
       
   178         case Krb5.ADDRTYPE_INET:        //Internet address
       
   179             if (new_address.length != 4)
       
   180                 throw new KrbApErrException(0, "Invalid Internet address");
       
   181             break;
       
   182         case Krb5.ADDRTYPE_CHAOS:
       
   183             if (new_address.length != 2) //CHAOSnet address
       
   184                 throw new KrbApErrException(0, "Invalid CHAOSnet address");
       
   185             break;
       
   186         case Krb5.ADDRTYPE_ISO:   // ISO address
       
   187             break;
       
   188         case Krb5.ADDRTYPE_IPX:   // XNS address
       
   189             if (new_address.length != 6)
       
   190                 throw new KrbApErrException(0, "Invalid XNS address");
       
   191             break;
       
   192         case Krb5.ADDRTYPE_APPLETALK:  //AppleTalk DDP address
       
   193             if (new_address.length != 3)
       
   194                 throw new KrbApErrException(0, "Invalid DDP address");
       
   195             break;
       
   196         case Krb5.ADDRTYPE_DECNET:    //DECnet Phase IV address
       
   197             if (new_address.length != 2)
       
   198                 throw new KrbApErrException(0, "Invalid DECnet Phase IV address");
       
   199             break;
       
   200         case Krb5.ADDRTYPE_INET6:     //Internet IPv6 address
       
   201             if (new_address.length != 16)
       
   202                 throw new KrbApErrException(0, "Invalid Internet IPv6 address");
       
   203             break;
       
   204         }
       
   205 
       
   206         addrType = new_addrType;
       
   207         if (new_address != null) {
       
   208            address = new_address.clone();
       
   209         }
       
   210         if (DEBUG) {
       
   211             if (addrType == Krb5.ADDRTYPE_INET ||
       
   212                 addrType == Krb5.ADDRTYPE_INET6) {
       
   213                 System.out.println("Host address is " +
       
   214                         InetAddress.getByAddress(address));
       
   215             }
       
   216         }
       
   217     }
       
   218 
       
   219     public HostAddress(InetAddress inetAddress) {
       
   220         addrType = getAddrType(inetAddress);
       
   221         address = inetAddress.getAddress();
       
   222     }
       
   223 
       
   224     /**
       
   225      * Constructs a host address from a single DER-encoded value.
       
   226      * @param encoding a single DER-encoded value.
       
   227      * @exception Asn1Exception if an error occurs while decoding an ASN1 encoded data.
       
   228      * @exception IOException if an I/O error occurs while reading encoded data.
       
   229      *
       
   230      */
       
   231     public HostAddress(DerValue encoding) throws Asn1Exception, IOException {
       
   232         DerValue der = encoding.getData().getDerValue();
       
   233         if ((der.getTag() & (byte)0x1F) == (byte)0x00) {
       
   234             addrType = der.getData().getBigInteger().intValue();
       
   235         }
       
   236         else
       
   237             throw new Asn1Exception(Krb5.ASN1_BAD_ID);
       
   238         der = encoding.getData().getDerValue();
       
   239         if ((der.getTag() & (byte)0x1F) == (byte)0x01) {
       
   240             address = der.getData().getOctetString();
       
   241         }
       
   242         else
       
   243             throw new Asn1Exception(Krb5.ASN1_BAD_ID);
       
   244         if (encoding.getData().available() > 0)
       
   245             throw new Asn1Exception(Krb5.ASN1_BAD_ID);
       
   246     }
       
   247 
       
   248     /**
       
   249          * Encodes a HostAddress object.
       
   250          * @return a byte array of encoded HostAddress object.
       
   251          * @exception Asn1Exception if an error occurs while decoding an ASN1 encoded data.
       
   252          * @exception IOException if an I/O error occurs while reading encoded data.
       
   253          *
       
   254          */
       
   255 
       
   256     public byte[] asn1Encode() throws Asn1Exception, IOException {
       
   257         DerOutputStream bytes = new DerOutputStream();
       
   258         DerOutputStream temp = new DerOutputStream();
       
   259         temp.putInteger(this.addrType);
       
   260         bytes.write(DerValue.createTag(DerValue.TAG_CONTEXT, true, (byte)0x00), temp);
       
   261         temp = new DerOutputStream();
       
   262         temp.putOctetString(address);
       
   263         bytes.write(DerValue.createTag(DerValue.TAG_CONTEXT, true, (byte)0x01), temp);
       
   264         temp = new DerOutputStream();
       
   265         temp.write(DerValue.tag_Sequence, bytes);
       
   266         return temp.toByteArray();
       
   267     }
       
   268 
       
   269     /**
       
   270      * Parses (unmarshal) a host address from a DER input stream.  This form
       
   271      * parsing might be used when expanding a value which is part of
       
   272          * a constructed sequence and uses explicitly tagged type.
       
   273      *
       
   274      * @exception Asn1Exception on error.
       
   275      * @exception IOException if an I/O error occurs while reading encoded data.
       
   276      * @param data the Der input stream value, which contains one or more marshaled value.
       
   277      * @param explicitTag tag number.
       
   278      * @param optional indicates if this data field is optional
       
   279      * @return an instance of HostAddress.
       
   280      *
       
   281      */
       
   282     public static HostAddress parse(DerInputStream data, byte explicitTag,
       
   283                                     boolean optional)
       
   284         throws Asn1Exception, IOException{
       
   285         if ((optional) &&
       
   286             (((byte)data.peekByte() & (byte)0x1F) != explicitTag)) {
       
   287             return null;
       
   288         }
       
   289         DerValue der = data.getDerValue();
       
   290         if (explicitTag != (der.getTag() & (byte)0x1F))  {
       
   291             throw new Asn1Exception(Krb5.ASN1_BAD_ID);
       
   292         }
       
   293         else {
       
   294             DerValue subDer = der.getData().getDerValue();
       
   295             return new HostAddress(subDer);
       
   296         }
       
   297     }
       
   298 
       
   299     @Override
       
   300     public String toString() {
       
   301         StringBuilder sb = new StringBuilder();
       
   302         sb.append(Arrays.toString(address));
       
   303         sb.append('(').append(addrType).append(')');
       
   304         return sb.toString();
       
   305     }
       
   306 }