OpenCores
URL https://opencores.org/ocsvn/openrisc/openrisc/trunk

Subversion Repositories openrisc

[/] [openrisc/] [trunk/] [gnu-dev/] [or1k-gcc/] [libjava/] [classpath/] [gnu/] [javax/] [crypto/] [sasl/] [SaslInputStream.java] - Blame information for rev 769

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 769 jeremybenn
/* SaslInputStream.java --
2
   Copyright (C) 2003, 2006 Free Software Foundation, Inc.
3
 
4
This file is a part of GNU Classpath.
5
 
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.
10
 
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.
15
 
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
20
 
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.
25
 
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.  */
37
 
38
 
39
package gnu.javax.crypto.sasl;
40
 
41
import gnu.java.security.Configuration;
42
import gnu.java.security.util.Util;
43
 
44
import java.io.IOException;
45
import java.io.InputStream;
46
import java.io.InterruptedIOException;
47
import java.util.logging.Logger;
48
 
49
import javax.security.sasl.Sasl;
50
import javax.security.sasl.SaslClient;
51
import javax.security.sasl.SaslServer;
52
 
53
/**
54
 * An input stream that uses either a {@link SaslClient} or a {@link SaslServer}
55
 * to process the data through these entities' security layer filter(s).
56
 */
57
public class SaslInputStream
58
    extends InputStream
59
{
60
  private static final Logger log = Logger.getLogger(SaslInputStream.class.getName());
61
  private SaslClient client;
62
  private SaslServer server;
63
  private int maxRawSendSize;
64
  private InputStream source;
65
  private byte[] internalBuf;
66
 
67
  public SaslInputStream(SaslClient client, InputStream source)
68
      throws IOException
69
  {
70
    super();
71
 
72
    this.client = client;
73
    String size = (String) client.getNegotiatedProperty(Sasl.RAW_SEND_SIZE);
74
    maxRawSendSize = Integer.parseInt(size);
75
    server = null;
76
    this.source = source;
77
  }
78
 
79
  public SaslInputStream(SaslServer server, InputStream source)
80
      throws IOException
81
  {
82
    super();
83
 
84
    this.server = server;
85
    String size = (String) server.getNegotiatedProperty(Sasl.RAW_SEND_SIZE);
86
    maxRawSendSize = Integer.parseInt(size);
87
    client = null;
88
    this.source = source;
89
  }
90
 
91
  public int available() throws IOException
92
  {
93
    return (internalBuf == null) ? 0 : internalBuf.length;
94
  }
95
 
96
  public void close() throws IOException
97
  {
98
    source.close();
99
  }
100
 
101
  /**
102
   * Reads the next byte of data from the input stream. The value byte is
103
   * returned as an <code>int</code> in the range <code>0</code> to
104
   * <code>255</code>. If no byte is available because the end of the stream
105
   * has been reached, the value <code>-1</code> is returned. This method
106
   * blocks until input data is available, the end of the stream is detected, or
107
   * an exception is thrown.
108
   * <p>
109
   * From a SASL mechanism provider's perspective, if a security layer has been
110
   * negotiated, the underlying <i>source</i> is expected to contain SASL
111
   * buffers, as defined in RFC 2222. Four octets in network byte order in the
112
   * front of each buffer identify the length of the buffer. The provider is
113
   * responsible for performing any integrity checking or other processing on
114
   * the buffer before returning the data as a stream of octets. For example,
115
   * the protocol driver's request for a single octet from the stream might;
116
   * i.e. an invocation of this method, may result in an entire SASL buffer
117
   * being read and processed before that single octet can be returned.
118
   *
119
   * @return the next byte of data, or <code>-1</code> if the end of the
120
   *         stream is reached.
121
   * @throws IOException if an I/O error occurs.
122
   */
123
  public int read() throws IOException
124
  {
125
    int result = -1;
126
    if (internalBuf != null && internalBuf.length > 0)
127
      {
128
        result = internalBuf[0] & 0xFF;
129
        if (internalBuf.length == 1)
130
          internalBuf = new byte[0];
131
        else
132
          {
133
            byte[] tmp = new byte[internalBuf.length - 1];
134
            System.arraycopy(internalBuf, 1, tmp, 0, tmp.length);
135
            internalBuf = tmp;
136
          }
137
      }
138
    else
139
      {
140
        byte[] buf = new byte[1];
141
        int check = read(buf);
142
        result = (check > 0) ? (buf[0] & 0xFF) : -1;
143
      }
144
    return result;
145
  }
146
 
147
  /**
148
   * Reads up to <code>len</code> bytes of data from the underlying <i>source</i>
149
   * input stream into an array of bytes. An attempt is made to read as many as
150
   * <code>len</code> bytes, but a smaller number may be read, possibly zero.
151
   * The number of bytes actually read is returned as an integer.
152
   * <p>
153
   * This method blocks until input data is available, end of file is detected,
154
   * or an exception is thrown.
155
   * <p>
156
   * If <code>b</code> is <code>null</code>, a {@link NullPointerException}
157
   * is thrown.
158
   * <p>
159
   * If <code>off</code> is negative, or <code>len</code> is negative, or
160
   * <code>off+len</code> is greater than the length of the array
161
   * <code>b</code>, then an {@link IndexOutOfBoundsException} is thrown.
162
   * <p>
163
   * If <code>len</code> is zero, then no bytes are read and <code>0</code>
164
   * is returned; otherwise, there is an attempt to read at least one byte. If
165
   * no byte is available because the stream is at end of file, the value
166
   * <code>-1</code> is returned; otherwise, at least one byte is read and
167
   * stored into <code>b</code>.
168
   * <p>
169
   * The first byte read is stored into element <code>b[off]</code>, the next
170
   * one into <code>b[off+1]</code>, and so on. The number of bytes read is,
171
   * at most, equal to <code>len</code>. Let <code>k</code> be the number
172
   * of bytes actually read; these bytes will be stored in elements
173
   * <code>b[off]</code> through <code>b[off+k-1]</code>, leaving elements
174
   * <code>b[off+k]</code> through <code>b[off+len-1]</code> unaffected.
175
   * <p>
176
   * In every case, elements <code>b[0]</code> through <code>b[off]</code>
177
   * and elements <code>b[off+len]</code> through <code>b[b.length-1]</code>
178
   * are unaffected.
179
   * <p>
180
   * If the first byte cannot be read for any reason other than end of file,
181
   * then an {@link IOException} is thrown. In particular, an
182
   * {@link IOException} is thrown if the input stream has been closed.
183
   * <p>
184
   * From the SASL mechanism provider's perspective, if a security layer has
185
   * been negotiated, the underlying <i>source</i> is expected to contain SASL
186
   * buffers, as defined in RFC 2222. Four octets in network byte order in the
187
   * front of each buffer identify the length of the buffer. The provider is
188
   * responsible for performing any integrity checking or other processing on
189
   * the buffer before returning the data as a stream of octets. The protocol
190
   * driver's request for a single octet from the stream might result in an
191
   * entire SASL buffer being read and processed before that single octet can be
192
   * returned.
193
   *
194
   * @param b the buffer into which the data is read.
195
   * @param off the start offset in array <code>b</code> at which the data is
196
   *          wricodeen.
197
   * @param len the maximum number of bytes to read.
198
   * @return the total number of bytes read into the buffer, or <code>-1</code>
199
   *         if there is no more data because the end of the stream has been
200
   *         reached.
201
   * @throws IOException if an I/O error occurs.
202
   */
203
  public int read(byte[] b, int off, int len) throws IOException
204
  {
205
    if (Configuration.DEBUG)
206
      log.entering(this.getClass().getName(), "read", new Object[] {
207
          b, Integer.valueOf(off), Integer.valueOf(len)
208
      });
209
    if ((off < 0) || (off > b.length) || (len < 0) || ((off + len) > b.length)
210
        || ((off + len) < 0))
211
      throw new IndexOutOfBoundsException("off=" + off + ", len=" + len
212
                                          + ", b.length=" + b.length);
213
    if (len == 0)
214
      {
215
        if (Configuration.DEBUG)
216
          log.exiting(this.getClass().getName(), "read", Integer.valueOf(0));
217
        return 0;
218
      }
219
    if (Configuration.DEBUG)
220
      log.finer("Available: " + available());
221
    int result = 0;
222
    if (internalBuf == null || internalBuf.length < 1)
223
      try
224
        {
225
          internalBuf = readSaslBuffer();
226
          if (internalBuf == null)
227
            {
228
              if (Configuration.DEBUG)
229
                {
230
                  log.finer("Underlying stream empty. Returning -1");
231
                  log.exiting(this.getClass().getName(), "read",
232
                              Integer.valueOf(-1));
233
                }
234
              return -1;
235
            }
236
        }
237
      catch (InterruptedIOException x)
238
        {
239
          if (Configuration.DEBUG)
240
            {
241
              log.finer("Reading thread was interrupted. Returning -1");
242
              log.throwing(this.getClass().getName(), "read", x);
243
              log.exiting(this.getClass().getName(), "read",
244
                          Integer.valueOf(-1));
245
            }
246
          return -1;
247
        }
248
    if (len <= internalBuf.length)
249
      {
250
        result = len;
251
        System.arraycopy(internalBuf, 0, b, off, len);
252
        if (len == internalBuf.length)
253
          internalBuf = null;
254
        else
255
          {
256
            byte[] tmp = new byte[internalBuf.length - len];
257
            System.arraycopy(internalBuf, len, tmp, 0, tmp.length);
258
            internalBuf = tmp;
259
          }
260
      }
261
    else
262
      {
263
        // first copy the available bytes to b
264
        result = internalBuf.length;
265
        System.arraycopy(internalBuf, 0, b, off, result);
266
        internalBuf = null;
267
        off += result;
268
        len -= result;
269
        int remaining; // count of bytes remaining in buffer after an iteration
270
        int delta; // count of bytes moved to b after an iteration
271
        int datalen;
272
        byte[] data;
273
        while (len > 0)
274
          // we need to read SASL buffers, as long as there are at least
275
          // 4 bytes available at the source
276
          if (source.available() > 3)
277
            {
278
              // process a buffer
279
              data = readSaslBuffer();
280
              if (data == null)
281
                {
282
                  if (Configuration.DEBUG)
283
                    log.finer("Underlying stream exhausted. Breaking...");
284
                  break;
285
                }
286
              datalen = data.length;
287
              // copy [part of] the result to b
288
              remaining = (datalen <= len) ? 0 : datalen - len;
289
              delta = datalen - remaining;
290
              System.arraycopy(data, 0, b, off, delta);
291
              if (remaining > 0)
292
                {
293
                  internalBuf = new byte[remaining];
294
                  System.arraycopy(data, delta, internalBuf, 0, remaining);
295
                }
296
              // update off, result and len
297
              off += delta;
298
              result += delta;
299
              len -= delta;
300
            }
301
          else
302
            { // nothing much we can do except return what we have
303
              if (Configuration.DEBUG)
304
                log.finer("Not enough bytes in source to read a buffer. Breaking...");
305
              break;
306
            }
307
      }
308
    if (Configuration.DEBUG)
309
      {
310
        log.finer("Remaining: "
311
                  + (internalBuf == null ? 0 : internalBuf.length));
312
        log.exiting(this.getClass().getName(), "read()", String.valueOf(result));
313
      }
314
    return result;
315
  }
316
 
317
  /**
318
   * Reads a SASL buffer from the underlying source if at least 4 bytes are
319
   * available.
320
   *
321
   * @return the byte[] of decoded buffer contents, or null if the underlying
322
   *         source was exhausted.
323
   * @throws IOException if an I/O exception occurs during the operation.
324
   */
325
  private byte[] readSaslBuffer() throws IOException
326
  {
327
    if (Configuration.DEBUG)
328
      log.entering(this.getClass().getName(), "readSaslBuffer()");
329
    int realLength; // check if we read as many bytes as we're supposed to
330
    byte[] result = new byte[4];
331
    try
332
      {
333
        realLength = source.read(result);
334
        if (realLength == -1)
335
          {
336
            if (Configuration.DEBUG)
337
              log.exiting(this.getClass().getName(), "readSaslBuffer");
338
            return null;
339
          }
340
      }
341
    catch (IOException x)
342
      {
343
        if (Configuration.DEBUG)
344
          log.throwing(this.getClass().getName(), "readSaslBuffer", x);
345
        throw x;
346
      }
347
    if (realLength != 4)
348
      throw new IOException("Was expecting 4 but found " + realLength);
349
    int bufferLength =  result[0]         << 24
350
                     | (result[1] & 0xFF) << 16
351
                     | (result[2] & 0xFF) << 8
352
                     | (result[3] & 0xFF);
353
    if (Configuration.DEBUG)
354
      log.finer("SASL buffer size: " + bufferLength);
355
    if (bufferLength > maxRawSendSize || bufferLength < 0)
356
      throw new SaslEncodingException("SASL buffer (security layer) too long");
357
 
358
    result = new byte[bufferLength];
359
    try
360
      {
361
        realLength = source.read(result);
362
      }
363
    catch (IOException x)
364
      {
365
        if (Configuration.DEBUG)
366
          log.throwing(this.getClass().getName(), "readSaslBuffer", x);
367
        throw x;
368
      }
369
    if (realLength != bufferLength)
370
      throw new IOException("Was expecting " + bufferLength + " but found "
371
                            + realLength);
372
    if (Configuration.DEBUG)
373
      {
374
        log.finer("Incoming buffer (before security) (hex): "
375
                  + Util.dumpString(result));
376
        log.finer("Incoming buffer (before security) (str): \""
377
                  + new String(result) + "\"");
378
      }
379
    if (client != null)
380
      result = client.unwrap(result, 0, realLength);
381
    else
382
      result = server.unwrap(result, 0, realLength);
383
    if (Configuration.DEBUG)
384
      {
385
        log.finer("Incoming buffer (after security) (hex): "
386
                  + Util.dumpString(result));
387
        log.finer("Incoming buffer (after security) (str): \""
388
                  + new String(result) + "\"");
389
        log.exiting(this.getClass().getName(), "readSaslBuffer");
390
      }
391
    return result;
392
  }
393
}

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.