2 Copyright (C) 2003, 2006 Free Software Foundation, Inc.
4 This file is a part of GNU Classpath.
6 GNU Classpath is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2 of the License, or (at
9 your option) any later version.
11 GNU Classpath is distributed in the hope that it will be useful, but
12 WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with GNU Classpath; if not, write to the Free Software
18 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
21 Linking this library statically or dynamically with other modules is
22 making a combined work based on this library. Thus, the terms and
23 conditions of the GNU General Public License cover the whole
26 As a special exception, the copyright holders of this library give you
27 permission to link this library with independent modules to produce an
28 executable, regardless of the license terms of these independent
29 modules, and to copy and distribute the resulting executable under
30 terms of your choice, provided that you also meet, for each linked
31 independent module, the terms and conditions of the license of that
32 module. An independent module is a module which is not derived from
33 or based on this library. If you modify this library, you may extend
34 this exception to your version of the library, but you are not
35 obligated to do so. If you do not wish to do so, delete this
36 exception statement from your version. */
39 package gnu
.javax
.crypto
.sasl
;
41 import gnu
.java
.security
.Registry
;
43 import java
.io
.ByteArrayInputStream
;
44 import java
.io
.IOException
;
45 import java
.math
.BigInteger
;
48 * The implementation of an incoming SASL buffer.
50 * The data elements this class caters for are described in [1].
55 * href="http://www.ietf.org/internet-drafts/draft-burdis-cat-srp-sasl-09.txt">
56 * Secure Remote Password Authentication Mechanism</a>;<br/>
57 * draft-burdis-cat-srp-sasl-09,<br/> <a
58 * href="mailto:keith@rucus.ru.ac.za">Keith Burdis</a> and <a
59 * href="mailto:raif@forge.com.au">Raïf S. Naffah</a>.</li>
62 public class InputBuffer
64 /** The internal buffer stream containing the buffer's contents. */
65 protected ByteArrayInputStream in
;
66 /** The length of the buffer, according to its header. */
70 * Constructs a SASL buffer given the buffer's encoded form, including its
73 * @param frame the encoded form, including the header bytes, of a SASL
75 * @throws SaslEncodingException if the buffer is malformed.
77 public InputBuffer(byte[] frame
) throws SaslEncodingException
82 throw new SaslEncodingException("SASL buffer header too short");
83 length
= (frame
[0] & 0xFF) << 24
84 | (frame
[1] & 0xFF) << 16
85 | (frame
[2] & 0xFF) << 8
87 if (length
> Registry
.SASL_BUFFER_MAX_LIMIT
|| length
< 0)
88 throw new SaslEncodingException("SASL buffer size limit exceeded");
89 in
= new ByteArrayInputStream(frame
, 4, length
);
92 /** Trivial private constructor for use by the class method. */
99 * Returns an instance of a SASL buffer given the buffer's encoded contents,
100 * excluding the buffer's header bytes.
102 * Calls the method with the same name and three arguments as:
103 * <code>getInstance(raw, 0, raw.length)</code>.
105 * @param raw the encoded form, excluding the header bytes, of a SASL buffer.
106 * @return a new instance of {@link InputBuffer}.
108 public static InputBuffer
getInstance(byte[] raw
)
110 return getInstance(raw
, 0, raw
.length
);
114 * Returns an instance of a SASL buffer given the buffer's encoded contents,
115 * excluding the buffer's header bytes.
117 * @param raw the encoded form, excluding the header bytes, of a SASL buffer.
118 * @param offset offset where to start using raw bytes from.
119 * @param len number of bytes to use.
120 * @return a new instance of {@link InputBuffer}.
122 public static InputBuffer
getInstance(byte[] raw
, int offset
, int len
)
124 InputBuffer result
= new InputBuffer();
125 result
.in
= new ByteArrayInputStream(raw
, offset
, len
);
130 * Converts two octets into the number that they represent.
132 * @param b the two octets.
133 * @return the length.
135 public static int twoBytesToLength(byte[] b
) throws SaslEncodingException
137 final int result
= (b
[0] & 0xFF) << 8 | (b
[1] & 0xFF);
138 if (result
> Registry
.SASL_TWO_BYTE_MAX_LIMIT
)
139 throw new SaslEncodingException("SASL MPI/Text size limit exceeded");
143 public boolean hasMoreElements()
145 return (in
.available() > 0);
149 * Decodes a SASL scalar quantity, <code>count</code>-octet long, from the
152 * @param count the number of octets of this scalar quantity.
153 * @return a native representation of a SASL scalar (unsigned integer)
155 * @throws SaslEncodingException if an encoding exception occurs during the
157 * @throws IOException if any other I/O exception occurs during the operation.
159 public long getScalar(int count
) throws IOException
161 if (count
< 0 || count
> 4)
162 throw new SaslEncodingException("Invalid SASL scalar octet count: "
163 + String
.valueOf(count
));
164 if (! hasMoreElements())
165 throw new SaslEncodingException("Not enough bytes for a scalar in buffer");
166 if (in
.available() < count
)
167 throw new SaslEncodingException("Illegal SASL scalar encoding");
168 byte[] element
= new byte[count
];
171 for (int i
= 0; i
< count
; i
++)
174 result
|= element
[i
] & 0xFFL
;
180 * Decodes a SASL OS from the current buffer.
182 * @return a native representation of a SASL OS.
183 * @throws SaslEncodingException if an encoding exception occurs during the
185 * @throws IOException if any other I/O exception occurs during the operation.
187 public byte[] getOS() throws IOException
189 if (! hasMoreElements())
190 throw new SaslEncodingException(
191 "Not enough bytes for an octet-sequence in buffer");
192 final int elementLength
= in
.read();
193 if (elementLength
> Registry
.SASL_ONE_BYTE_MAX_LIMIT
)
194 throw new SaslEncodingException("SASL octet-sequence size limit exceeded");
195 if (in
.available() < elementLength
)
196 throw new SaslEncodingException("Illegal SASL octet-sequence encoding");
197 byte[] result
= new byte[elementLength
];
203 * Decodes a SASL EOS from the current buffer.
205 * @return a native representation of a SASL EOS.
206 * @throws SaslEncodingException if an encoding exception occurs during the
208 * @throws IOException if any other I/O exception occurs during the operation.
210 public byte[] getEOS() throws IOException
212 if (in
.available() < 2)
213 throw new SaslEncodingException(
214 "Not enough bytes for an extended octet-sequence in buffer");
215 byte[] elementLengthBytes
= new byte[2];
216 in
.read(elementLengthBytes
);
217 final int elementLength
= twoBytesToLength(elementLengthBytes
);
218 if (in
.available() < elementLength
)
219 throw new SaslEncodingException(
220 "Illegal SASL extended octet-sequence encoding");
221 byte[] result
= new byte[elementLength
];
227 * Decodes a SASL MPI from the current buffer.
229 * @return a native representation of a SASL MPI.
230 * @throws SaslEncodingException if an encoding exception occurs during the
232 * @throws IOException if any other I/O exception occurs during the operation.
234 public BigInteger
getMPI() throws IOException
236 if (in
.available() < 2)
237 throw new SaslEncodingException("Not enough bytes for an MPI in buffer");
238 byte[] elementLengthBytes
= new byte[2];
239 in
.read(elementLengthBytes
);
240 final int elementLength
= twoBytesToLength(elementLengthBytes
);
241 if (in
.available() < elementLength
)
242 throw new SaslEncodingException(
243 "Illegal SASL multi-precision integer encoding");
244 byte[] element
= new byte[elementLength
];
246 return new BigInteger(1, element
);
250 * Decodes a SASL Text from the current buffer.
252 * @return a native representation of a SASL Text.
253 * @throws SaslEncodingException if an encoding exception occurs during the
255 * @throws SaslEncodingException if the UTF-8 character encoding is not
256 * supported on this platform.
257 * @throws IOException if any other I/O exception occurs during the operation.
259 public String
getText() throws IOException
261 if (in
.available() < 2)
262 throw new SaslEncodingException("Not enough bytes for a text in buffer");
263 byte[] elementLengthBytes
= new byte[2];
264 in
.read(elementLengthBytes
);
265 final int elementLength
= twoBytesToLength(elementLengthBytes
);
266 if (in
.available() < elementLength
)
267 throw new SaslEncodingException("Illegal SASL text encoding");
268 byte[] element
= new byte[elementLength
];
270 return new String(element
, "UTF8");