Docjar: A Java Source and Docuemnt Enginecom.*    java.*    javax.*    org.*    all    new    plug-in

Quick Search    Search Deep

Source code: mindbright/ssh/SSHPduInputStream.java


1   /******************************************************************************
2    *
3    * Copyright (c) 1998,99 by Mindbright Technology AB, Stockholm, Sweden.
4    *                 www.mindbright.se, info@mindbright.se
5    *
6    * This program 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
9    * (at your option) any later version.
10   *
11   * This program is distributed in the hope that it will be useful,
12   * but WITHOUT ANY WARRANTY; without even the implied warranty of
13   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14   * GNU General Public License for more details.
15   *
16   *****************************************************************************
17   * $Author: nallen $
18   * $Date: 2001/11/12 16:31:20 $
19   * $Name:  $
20   *****************************************************************************/
21  package mindbright.ssh;
22  
23  import java.io.*;
24  import java.math.BigInteger;
25  
26  import mindbright.security.*;
27  import mindbright.util.*;
28  
29  public final class SSHPduInputStream extends SSHDataInputStream implements SSHPdu {
30  
31    static final class PduByteArrayInputStream extends ByteArrayInputStream {
32      PduByteArrayInputStream(byte[] data) {
33        super(data);
34      }
35      public int getPos() {
36        return pos;
37      }
38      public void setPos(int pos) {
39        this.pos = pos;
40      }
41      public byte[] getBuf() {
42        return buf;
43      }
44      public void setBuf(byte[] buf) {
45        this.buf = buf;
46      }
47    }
48  
49    public int type;
50    public int length;
51  
52    byte[] bytes;
53    Cipher cipher;
54  
55    SSHPduInputStream(int type, Cipher cipher) {
56      super(null);
57      this.type   = type; // This is the expected type (checked in readFrom())
58      this.cipher = cipher;
59    }
60  
61    boolean validChecksum() throws IOException {
62      int padLen = ((length + 8) & ~7);
63      int stored, calculated;
64  
65      skip(padLen - 4);
66      stored = readInt();
67      reset();
68  
69      calculated = (int)CRC32.getValue(bytes, 0, padLen - 4);
70  
71      if(calculated != stored)
72        return false;
73  
74      return true;
75    }
76  
77    public SSHPdu createPdu() {
78      return new SSHPduInputStream(this.type, this.cipher);
79    }
80  
81    public void readFrom(InputStream in) throws IOException {
82      SSHDataInputStream dIn    = new SSHDataInputStream(in);
83      int                len    = dIn.readInt();
84      int                padLen = ((len + 8) & ~7);
85      int                type;
86      byte[]             data;
87  
88      if(padLen > 256000)
89        throw new IOException("Corrupt incoming packet, too large");
90  
91      data = new byte[padLen];
92  
93      dIn.readFully(data);
94      if(cipher != null)
95        cipher.decrypt(data, 0, data, 0, padLen);
96  
97      this.in     = new PduByteArrayInputStream(data);
98      this.bytes  = data;
99      this.length = len;
100 
101     if(!this.validChecksum())
102       throw new IOException("Invalid checksum in packet");
103 
104     this.skip(8 - (len % 8));
105     type = (int)this.readByte();
106 
107     if(type == SSH.MSG_DEBUG) {
108       SSH.logDebug("MSG_DEBUG: " + this.readString());
109       this.readFrom(in);
110     } else if(type == SSH.MSG_IGNORE) {
111       SSH.logIgnore(this);
112       this.readFrom(in);
113     } else {
114       if((this.type != SSH.MSG_ANY) && (this.type != type)) {
115   if(type == SSH.MSG_DISCONNECT)
116     throw new IOException("Server disconnected: " + this.readString());
117   else
118     throw new IOException("Invalid type: " + type + " (expected: " +
119         this.type + ")");
120       }
121       this.type = type;
122     }
123 
124   }
125 
126   public void writeTo(OutputStream sshOut) throws IOException {
127     int off, n;
128 
129     if(type != SSH.MSG_CHANNEL_DATA &&
130        type != SSH.SMSG_STDOUT_DATA &&
131        type != SSH.SMSG_STDERR_DATA)
132       throw new IOException("Trying to write raw data from non-data PDU");
133 
134     // Here we assume that the content left is readable through readString
135     // which is the case if this is SSH-data
136     //
137     int len = readInt();
138 
139     PduByteArrayInputStream is = (PduByteArrayInputStream)in;
140 
141     sshOut.write(bytes, is.getPos(), len);
142 
143     sshOut.flush();
144   }
145 
146   public byte[] rawData() {
147     return bytes;
148   }
149   public void rawSetData(byte[] raw) {
150     PduByteArrayInputStream is = (PduByteArrayInputStream)in;
151     bytes = new byte[raw.length + 4];
152     is.setPos(0);
153     int len = raw.length;
154     int off = 0;
155     bytes[off++] = (byte)((len >>> 24) & 0xff);
156     bytes[off++] = (byte)((len >>> 16) & 0xff);
157     bytes[off++] = (byte)((len >>> 8)  & 0xff);
158     bytes[off++] = (byte)(len & 0xff);
159     System.arraycopy(raw, 0, bytes, off, raw.length);
160     is.setBuf(bytes);
161   }
162   public int rawOffset() {
163     PduByteArrayInputStream is = (PduByteArrayInputStream)in;
164     return is.getPos() + 4; // The first four bytes is the length of the data
165   }
166   public int rawSize() {
167     PduByteArrayInputStream is = (PduByteArrayInputStream)in;
168     int off = is.getPos();
169     int ch1 = ((bytes[off++] + 256) & 0xff);
170     int ch2 = ((bytes[off++] + 256) & 0xff);
171     int ch3 = ((bytes[off++] + 256) & 0xff);
172     int ch4 = ((bytes[off]   + 256) & 0xff);
173     return ((ch1 << 24) + (ch2 << 16) + (ch3 << 8) + (ch4 << 0));
174   }
175   // !!! Only allowed to shrink for now !!!
176   public void rawAdjustSize(int size) {
177     PduByteArrayInputStream is = (PduByteArrayInputStream)in;
178     int oldSz = rawSize();
179     if(size >= oldSz)
180       return;
181     int pos = is.getPos() + (oldSz - size);
182     is.setPos(pos);
183     bytes[pos++] = (byte)((size >>> 24) & 0xff);
184     bytes[pos++] = (byte)((size >>> 16) & 0xff);
185     bytes[pos++] = (byte)((size >>> 8)  & 0xff);
186     bytes[pos++] = (byte) (size & 0xff);
187   }
188 
189 }