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