/* SaslInputStream.java -- 
   Copyright (C) 2003, 2006 Free Software Foundation, Inc.

This file is a part of GNU Classpath.

GNU Classpath is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or (at
your option) any later version.

GNU Classpath is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
General Public License for more details.

You should have received a copy of the GNU General Public License
along with GNU Classpath; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
USA

Linking this library statically or dynamically with other modules is
making a combined work based on this library.  Thus, the terms and
conditions of the GNU General Public License cover the whole
combination.

As a special exception, the copyright holders of this library give you
permission to link this library with independent modules to produce an
executable, regardless of the license terms of these independent
modules, and to copy and distribute the resulting executable under
terms of your choice, provided that you also meet, for each linked
independent module, the terms and conditions of the license of that
module.  An independent module is a module which is not derived from
or based on this library.  If you modify this library, you may extend
this exception to your version of the library, but you are not
obligated to do so.  If you do not wish to do so, delete this
exception statement from your version.  */


package gnu.javax.crypto.sasl;

import gnu.java.security.Configuration;
import gnu.java.security.util.Util;

import java.io.IOException;
import java.io.InputStream;
import java.io.InterruptedIOException;
import java.util.logging.Logger;

import javax.security.sasl.Sasl;
import javax.security.sasl.SaslClient;
import javax.security.sasl.SaslServer;

/**
 * An input stream that uses either a {@link SaslClient} or a {@link SaslServer}
 * to process the data through these entities' security layer filter(s).
 */
public class SaslInputStream
    extends InputStream
{
  private static final Logger log = Logger.getLogger(SaslInputStream.class.getName());
  private SaslClient client;
  private SaslServer server;
  private int maxRawSendSize;
  private InputStream source;
  private byte[] internalBuf;

  public SaslInputStream(SaslClient client, InputStream source)
      throws IOException
  {
    super();

    this.client = client;
    String size = (String) client.getNegotiatedProperty(Sasl.RAW_SEND_SIZE);
    maxRawSendSize = Integer.parseInt(size);
    server = null;
    this.source = source;
  }

  public SaslInputStream(SaslServer server, InputStream source)
      throws IOException
  {
    super();

    this.server = server;
    String size = (String) server.getNegotiatedProperty(Sasl.RAW_SEND_SIZE);
    maxRawSendSize = Integer.parseInt(size);
    client = null;
    this.source = source;
  }

  public int available() throws IOException
  {
    return (internalBuf == null) ? 0 : internalBuf.length;
  }

  public void close() throws IOException
  {
    source.close();
  }

  /**
   * Reads the next byte of data from the input stream. The value byte is
   * returned as an <code>int</code> in the range <code>0</code> to
   * <code>255</code>. If no byte is available because the end of the stream
   * has been reached, the value <code>-1</code> is returned. This method
   * blocks until input data is available, the end of the stream is detected, or
   * an exception is thrown.
   * <p>
   * From a SASL mechanism provider's perspective, if a security layer has been
   * negotiated, the underlying <i>source</i> is expected to contain SASL
   * buffers, as defined in RFC 2222. Four octets in network byte order in the
   * front of each buffer identify the length of the buffer. The provider is
   * responsible for performing any integrity checking or other processing on
   * the buffer before returning the data as a stream of octets. For example,
   * the protocol driver's request for a single octet from the stream might;
   * i.e. an invocation of this method, may result in an entire SASL buffer
   * being read and processed before that single octet can be returned.
   * 
   * @return the next byte of data, or <code>-1</code> if the end of the
   *         stream is reached.
   * @throws IOException if an I/O error occurs.
   */
  public int read() throws IOException
  {
    int result = -1;
    if (internalBuf != null && internalBuf.length > 0)
      {
        result = internalBuf[0] & 0xFF;
        if (internalBuf.length == 1)
          internalBuf = new byte[0];
        else
          {
            byte[] tmp = new byte[internalBuf.length - 1];
            System.arraycopy(internalBuf, 1, tmp, 0, tmp.length);
            internalBuf = tmp;
          }
      }
    else
      {
        byte[] buf = new byte[1];
        int check = read(buf);
        result = (check > 0) ? (buf[0] & 0xFF) : -1;
      }
    return result;
  }

  /**
   * Reads up to <code>len</code> bytes of data from the underlying <i>source</i>
   * input stream into an array of bytes. An attempt is made to read as many as
   * <code>len</code> bytes, but a smaller number may be read, possibly zero.
   * The number of bytes actually read is returned as an integer.
   * <p>
   * This method blocks until input data is available, end of file is detected,
   * or an exception is thrown.
   * <p>
   * If <code>b</code> is <code>null</code>, a {@link NullPointerException}
   * is thrown.
   * <p>
   * If <code>off</code> is negative, or <code>len</code> is negative, or
   * <code>off+len</code> is greater than the length of the array
   * <code>b</code>, then an {@link IndexOutOfBoundsException} is thrown.
   * <p>
   * If <code>len</code> is zero, then no bytes are read and <code>0</code>
   * is returned; otherwise, there is an attempt to read at least one byte. If
   * no byte is available because the stream is at end of file, the value
   * <code>-1</code> is returned; otherwise, at least one byte is read and
   * stored into <code>b</code>.
   * <p>
   * The first byte read is stored into element <code>b[off]</code>, the next
   * one into <code>b[off+1]</code>, and so on. The number of bytes read is,
   * at most, equal to <code>len</code>. Let <code>k</code> be the number
   * of bytes actually read; these bytes will be stored in elements
   * <code>b[off]</code> through <code>b[off+k-1]</code>, leaving elements
   * <code>b[off+k]</code> through <code>b[off+len-1]</code> unaffected.
   * <p>
   * In every case, elements <code>b[0]</code> through <code>b[off]</code>
   * and elements <code>b[off+len]</code> through <code>b[b.length-1]</code>
   * are unaffected.
   * <p>
   * If the first byte cannot be read for any reason other than end of file,
   * then an {@link IOException} is thrown. In particular, an
   * {@link IOException} is thrown if the input stream has been closed.
   * <p>
   * From the SASL mechanism provider's perspective, if a security layer has
   * been negotiated, the underlying <i>source</i> is expected to contain SASL
   * buffers, as defined in RFC 2222. Four octets in network byte order in the
   * front of each buffer identify the length of the buffer. The provider is
   * responsible for performing any integrity checking or other processing on
   * the buffer before returning the data as a stream of octets. The protocol
   * driver's request for a single octet from the stream might result in an
   * entire SASL buffer being read and processed before that single octet can be
   * returned.
   * 
   * @param b the buffer into which the data is read.
   * @param off the start offset in array <code>b</code> at which the data is
   *          wricodeen.
   * @param len the maximum number of bytes to read.
   * @return the total number of bytes read into the buffer, or <code>-1</code>
   *         if there is no more data because the end of the stream has been
   *         reached.
   * @throws IOException if an I/O error occurs.
   */
  public int read(byte[] b, int off, int len) throws IOException
  {
    if (Configuration.DEBUG)
      log.entering(this.getClass().getName(), "read", new Object[] {
          b, Integer.valueOf(off), Integer.valueOf(len)
      });
    if ((off < 0) || (off > b.length) || (len < 0) || ((off + len) > b.length)
        || ((off + len) < 0))
      throw new IndexOutOfBoundsException("off=" + off + ", len=" + len
                                          + ", b.length=" + b.length);
    if (len == 0)
      {
        if (Configuration.DEBUG)
          log.exiting(this.getClass().getName(), "read", Integer.valueOf(0));
        return 0;
      }
    if (Configuration.DEBUG)
      log.finer("Available: " + available());
    int result = 0;
    if (internalBuf == null || internalBuf.length < 1)
      try
        {
          internalBuf = readSaslBuffer();
          if (internalBuf == null)
            {
              if (Configuration.DEBUG)
                {
                  log.finer("Underlying stream empty. Returning -1");
                  log.exiting(this.getClass().getName(), "read",
                              Integer.valueOf(-1));
                }
              return -1;
            }
        }
      catch (InterruptedIOException x)
        {
          if (Configuration.DEBUG)
            {
              log.finer("Reading thread was interrupted. Returning -1");
              log.throwing(this.getClass().getName(), "read", x);
              log.exiting(this.getClass().getName(), "read",
                          Integer.valueOf(-1));
            }
          return -1;
        }
    if (len <= internalBuf.length)
      {
        result = len;
        System.arraycopy(internalBuf, 0, b, off, len);
        if (len == internalBuf.length)
          internalBuf = null;
        else
          {
            byte[] tmp = new byte[internalBuf.length - len];
            System.arraycopy(internalBuf, len, tmp, 0, tmp.length);
            internalBuf = tmp;
          }
      }
    else
      {
        // first copy the available bytes to b
        result = internalBuf.length;
        System.arraycopy(internalBuf, 0, b, off, result);
        internalBuf = null;
        off += result;
        len -= result;
        int remaining; // count of bytes remaining in buffer after an iteration
        int delta; // count of bytes moved to b after an iteration
        int datalen;
        byte[] data;
        while (len > 0)
          // we need to read SASL buffers, as long as there are at least
          // 4 bytes available at the source
          if (source.available() > 3)
            {
              // process a buffer
              data = readSaslBuffer();
              if (data == null)
                {
                  if (Configuration.DEBUG)
                    log.finer("Underlying stream exhausted. Breaking...");
                  break;
                }
              datalen = data.length;
              // copy [part of] the result to b
              remaining = (datalen <= len) ? 0 : datalen - len;
              delta = datalen - remaining;
              System.arraycopy(data, 0, b, off, delta);
              if (remaining > 0)
                {
                  internalBuf = new byte[remaining];
                  System.arraycopy(data, delta, internalBuf, 0, remaining);
                }
              // update off, result and len
              off += delta;
              result += delta;
              len -= delta;
            }
          else
            { // nothing much we can do except return what we have
              if (Configuration.DEBUG)
                log.finer("Not enough bytes in source to read a buffer. Breaking...");
              break;
            }
      }
    if (Configuration.DEBUG)
      {
        log.finer("Remaining: "
                  + (internalBuf == null ? 0 : internalBuf.length));
        log.exiting(this.getClass().getName(), "read()", String.valueOf(result));
      }
    return result;
  }

  /**
   * Reads a SASL buffer from the underlying source if at least 4 bytes are
   * available.
   * 
   * @return the byte[] of decoded buffer contents, or null if the underlying
   *         source was exhausted.
   * @throws IOException if an I/O exception occurs during the operation.
   */
  private byte[] readSaslBuffer() throws IOException
  {
    if (Configuration.DEBUG)
      log.entering(this.getClass().getName(), "readSaslBuffer()");
    int realLength; // check if we read as many bytes as we're supposed to
    byte[] result = new byte[4];
    try
      {
        realLength = source.read(result);
        if (realLength == -1)
          {
            if (Configuration.DEBUG)
              log.exiting(this.getClass().getName(), "readSaslBuffer");
            return null;
          }
      }
    catch (IOException x)
      {
        if (Configuration.DEBUG)
          log.throwing(this.getClass().getName(), "readSaslBuffer", x);
        throw x;
      }
    if (realLength != 4)
      throw new IOException("Was expecting 4 but found " + realLength);
    int bufferLength =  result[0]         << 24
                     | (result[1] & 0xFF) << 16
                     | (result[2] & 0xFF) << 8
                     | (result[3] & 0xFF);
    if (Configuration.DEBUG)
      log.finer("SASL buffer size: " + bufferLength);
    if (bufferLength > maxRawSendSize || bufferLength < 0)
      throw new SaslEncodingException("SASL buffer (security layer) too long");

    result = new byte[bufferLength];
    try
      {
        realLength = source.read(result);
      }
    catch (IOException x)
      {
        if (Configuration.DEBUG)
          log.throwing(this.getClass().getName(), "readSaslBuffer", x);
        throw x;
      }
    if (realLength != bufferLength)
      throw new IOException("Was expecting " + bufferLength + " but found "
                            + realLength);
    if (Configuration.DEBUG)
      {
        log.finer("Incoming buffer (before security) (hex): "
                  + Util.dumpString(result));
        log.finer("Incoming buffer (before security) (str): \""
                  + new String(result) + "\"");
      }
    if (client != null)
      result = client.unwrap(result, 0, realLength);
    else
      result = server.unwrap(result, 0, realLength);
    if (Configuration.DEBUG)
      {
        log.finer("Incoming buffer (after security) (hex): "
                  + Util.dumpString(result));
        log.finer("Incoming buffer (after security) (str): \""
                  + new String(result) + "\"");
        log.exiting(this.getClass().getName(), "readSaslBuffer");
      }
    return result;
  }
}
