1/*
2 * Copyright (c) 2000, 2001, 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
26package org.ietf.jgss;
27
28import java.net.InetAddress;
29import java.util.Arrays;
30
31/**
32 * This class encapsulates the concept of caller-provided channel
33 * binding information. Channel bindings are used to strengthen the
34 * quality with which peer entity authentication is provided during
35 * context establishment.  They enable the GSS-API callers to bind the
36 * establishment of the security context to relevant characteristics
37 * like addresses or to application specific data.<p>
38 *
39 * The caller initiating the security context must determine the
40 * appropriate channel binding values to set in the GSSContext object.
41 * The acceptor must provide an identical binding in order to validate
42 * that received tokens possess correct channel-related characteristics.<p>
43 *
44 * Use of channel bindings is optional in GSS-API. ChannelBinding can be
45 * set for the {@link GSSContext GSSContext} using the {@link
46 * GSSContext#setChannelBinding(ChannelBinding) setChannelBinding} method
47 * before the first call to {@link GSSContext#initSecContext(byte[], int, int)
48 * initSecContext} or {@link GSSContext#acceptSecContext(byte[], int, int)
49 * acceptSecContext} has been performed.  Unless the <code>setChannelBinding</code>
50 * method has been used to set the ChannelBinding for a GSSContext object,
51 * <code>null</code> ChannelBinding will be assumed. <p>
52 *
53 * Conceptually, the GSS-API concatenates the initiator and acceptor
54 * address information, and the application supplied byte array to form an
55 * octet string.  The mechanism calculates a MIC over this octet string and
56 * binds the MIC to the context establishment token emitted by
57 * <code>initSecContext</code> method of the <code>GSSContext</code>
58 * interface.  The same bindings are set by the context acceptor for its
59 * <code>GSSContext</code> object and during processing of the
60 * <code>acceptSecContext</code> method a MIC is calculated in the same
61 * way. The calculated MIC is compared with that found in the token, and if
62 * the MICs differ, accept will throw a <code>GSSException</code> with the
63 * major code set to {@link GSSException#BAD_BINDINGS BAD_BINDINGS}, and
64 * the context will not be established. Some mechanisms may include the
65 * actual channel binding data in the token (rather than just a MIC);
66 * applications should therefore not use confidential data as
67 * channel-binding components.<p>
68 *
69 *  Individual mechanisms may impose additional constraints on addresses
70 *  that may appear in channel bindings.  For example, a mechanism may
71 *  verify that the initiator address field of the channel binding
72 *  contains the correct network address of the host system.  Portable
73 *  applications should therefore ensure that they either provide correct
74 *  information for the address fields, or omit setting of the addressing
75 *  information.
76 *
77 * @author Mayank Upadhyay
78 * @since 1.4
79 */
80public class ChannelBinding {
81
82    private InetAddress initiator;
83    private InetAddress acceptor;
84    private  byte[] appData;
85
86    /**
87     * Create a ChannelBinding object with user supplied address information
88     * and data.  <code>null</code> values can be used for any fields which the
89     * application does not want to specify.
90     *
91     * @param initAddr the address of the context initiator.
92     * <code>null</code> value can be supplied to indicate that the
93     * application does not want to set this value.
94     * @param acceptAddr the address of the context
95     * acceptor. <code>null</code> value can be supplied to indicate that
96     * the application does not want to set this value.
97     * @param appData application supplied data to be used as part of the
98     * channel bindings. <code>null</code> value can be supplied to
99     * indicate that the application does not want to set this value.
100     */
101    public ChannelBinding(InetAddress initAddr, InetAddress acceptAddr,
102                        byte[] appData) {
103
104        initiator = initAddr;
105        acceptor = acceptAddr;
106
107        if (appData != null) {
108            this.appData = new byte[appData.length];
109            java.lang.System.arraycopy(appData, 0, this.appData, 0,
110                                appData.length);
111        }
112    }
113
114    /**
115     * Creates a ChannelBinding object without any addressing information.
116     *
117     * @param appData application supplied data to be used as part of the
118     * channel bindings.
119     */
120    public ChannelBinding(byte[] appData) {
121        this(null, null, appData);
122    }
123
124    /**
125     * Get the initiator's address for this channel binding.
126     *
127     * @return the initiator's address. <code>null</code> is returned if
128     * the address has not been set.
129     */
130    public InetAddress getInitiatorAddress() {
131        return initiator;
132    }
133
134    /**
135     * Get the acceptor's address for this channel binding.
136     *
137     * @return the acceptor's address. null is returned if the address has
138     * not been set.
139     */
140    public InetAddress getAcceptorAddress() {
141        return acceptor;
142    }
143
144    /**
145     * Get the application specified data for this channel binding.
146     *
147     * @return the application data being used as part of the
148     * ChannelBinding. <code>null</code> is returned if no application data
149     * has been specified for the channel binding.
150     */
151    public byte[] getApplicationData() {
152
153        if (appData == null) {
154            return null;
155        }
156
157        byte[] retVal = new byte[appData.length];
158        System.arraycopy(appData, 0, retVal, 0, appData.length);
159        return retVal;
160    }
161
162    /**
163     * Compares two instances of ChannelBinding.
164     *
165     * @param obj another ChannelBinding to compare this one with
166     * @return true if the two ChannelBinding's contain
167     * the same values for the initiator and acceptor addresses and the
168     * application data.
169     */
170    public boolean equals(Object obj) {
171
172        if (this == obj)
173            return true;
174
175        if (! (obj instanceof ChannelBinding))
176            return false;
177
178        ChannelBinding cb = (ChannelBinding) obj;
179
180        if ((initiator != null && cb.initiator == null) ||
181            (initiator == null && cb.initiator != null))
182            return false;
183
184        if (initiator != null && !initiator.equals(cb.initiator))
185            return false;
186
187        if ((acceptor != null && cb.acceptor == null) ||
188            (acceptor == null && cb.acceptor != null))
189            return false;
190
191        if (acceptor != null && !acceptor.equals(cb.acceptor))
192            return false;
193
194        return Arrays.equals(appData, cb.appData);
195    }
196
197    /**
198     * Returns a hashcode value for this ChannelBinding object.
199     *
200     * @return a hashCode value
201     */
202    public int hashCode() {
203        if (initiator != null)
204            return initiator.hashCode();
205        else if (acceptor != null)
206            return acceptor.hashCode();
207        else if (appData != null)
208            return new String(appData).hashCode();
209        else
210            return 1;
211    }
212}
213