2006-08-14 Mark Wielaard <mark@klomp.org>
[official-gcc.git] / libjava / classpath / gnu / javax / crypto / sasl / InputBuffer.java
blobd676a595dc59b1ce0218e2fe153322a4a4690bac
1 /* InputBuffer.java --
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
19 USA
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
24 combination.
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;
47 /**
48 * The implementation of an incoming SASL buffer.
49 * <p>
50 * The data elements this class caters for are described in [1].
51 * <p>
52 * References:
53 * <ol>
54 * <li><a
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&iuml;f S. Naffah</a>.</li>
60 * </ol>
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. */
67 protected int length;
69 /**
70 * Constructs a SASL buffer given the buffer's encoded form, including its
71 * header bytes.
73 * @param frame the encoded form, including the header bytes, of a SASL
74 * buffer.
75 * @throws SaslEncodingException if the buffer is malformed.
77 public InputBuffer(byte[] frame) throws SaslEncodingException
79 this();
81 if (frame.length < 4)
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
86 | (frame[3] & 0xFF);
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. */
93 private InputBuffer()
95 super();
98 /**
99 * Returns an instance of a SASL buffer given the buffer's encoded contents,
100 * excluding the buffer's header bytes.
101 * <p>
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);
126 return result;
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");
140 return result;
143 public boolean hasMoreElements()
145 return (in.available() > 0);
149 * Decodes a SASL scalar quantity, <code>count</code>-octet long, from the
150 * current buffer.
152 * @param count the number of octets of this scalar quantity.
153 * @return a native representation of a SASL scalar (unsigned integer)
154 * quantity.
155 * @throws SaslEncodingException if an encoding exception occurs during the
156 * operation.
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];
169 in.read(element);
170 long result = 0L;
171 for (int i = 0; i < count; i++)
173 result <<= 8;
174 result |= element[i] & 0xFFL;
176 return result;
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
184 * operation.
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];
198 in.read(result);
199 return result;
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
207 * operation.
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];
222 in.read(result);
223 return result;
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
231 * operation.
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];
245 in.read(element);
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
254 * operation.
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];
269 in.read(element);
270 return new String(element, "UTF8");