2006-09-14 Jonathan Chambers <joncham@gmail.com>
[mcs.git] / class / Novell.Directory.Ldap / Novell.Directory.Ldap.Security.jvm / SecureStream.cs
blobf9aa4e43aecdef9b61ba797d1951f0fbf1722ef5
1 //
2 // Novell.Directory.Ldap.Security.SecureStream.cs
3 //
4 // Authors:
5 // Boris Kirzner <borsk@mainsoft.com>
6 // Konstantin Triger <kostat@mainsoft.com>
7 //
8 // (C) 2005 Mainsoft Corporation (http://www.mainsoft.com)
9 //
12 // Permission is hereby granted, free of charge, to any person obtaining
13 // a copy of this software and associated documentation files (the
14 // "Software"), to deal in the Software without restriction, including
15 // without limitation the rights to use, copy, modify, merge, publish,
16 // distribute, sublicense, and/or sell copies of the Software, and to
17 // permit persons to whom the Software is furnished to do so, subject to
18 // the following conditions:
19 //
20 // The above copyright notice and this permission notice shall be
21 // included in all copies or substantial portions of the Software.
22 //
23 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
24 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
25 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
26 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
27 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
28 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
29 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
32 using System;
33 using System.IO;
35 namespace Novell.Directory.Ldap.Security
37 internal class SecureStream : Stream
39 #region Fields
41 private readonly Stream _stream;
42 private readonly Krb5Helper _helper;
44 private readonly byte [] _lenBuf = new byte [4];
45 private byte [] _buffer;
46 private int _bufferPosition;
48 #endregion // Fields
50 #region Constructors
52 public SecureStream(Stream stream, Krb5Helper helper): base ()
54 _stream = stream;
55 _helper = helper;
58 #endregion // Constructors
60 #region Properties
62 public override bool CanRead
64 get { return _stream.CanRead; }
67 public override bool CanSeek
69 get { return _stream.CanSeek; }
72 public override bool CanWrite
74 get { return _stream.CanWrite; }
77 public override long Length
79 get { throw new NotSupportedException (); }
82 public override long Position
84 get { throw new NotSupportedException (); }
85 set { throw new NotSupportedException (); }
88 #endregion // Properties
90 #region Methods
92 public override void Flush()
94 _stream.Flush ();
97 public override int Read( byte [] buffer, int offset, int count)
99 if (_buffer == null || _bufferPosition >= _buffer.Length) {
100 int actual = Fill ();
101 while (actual == 0)
102 actual = Fill ();
104 if (actual == -1)
105 return -1;
108 int available = _buffer.Length - _bufferPosition;
109 if (count > available) {
110 Array.Copy (_buffer, _bufferPosition, buffer, offset, available);
111 _bufferPosition = _buffer.Length;
112 return available;
114 else {
115 Array.Copy (_buffer, _bufferPosition, buffer, offset, count);
116 _bufferPosition += count;
117 return count;
121 public override void Close() {
122 _stream.Close();
123 _helper.Dispose();
126 private int Fill()
128 int actual = ReadAll (_lenBuf, 4);
130 if (actual != 4)
131 return -1;
133 int length = NetworkByteOrderToInt (_lenBuf, 0, 4);
135 // if (length > _recvMaxBufSize)
136 // throw new LdapException(length + " exceeds the negotiated receive buffer size limit: " + _recvMaxBufSize, 80, "");
138 byte [] rawBuffer = new byte [length];
139 actual = ReadAll (rawBuffer, length);
141 if (actual != length)
142 throw new LdapException("Expected to read " + length + " bytes, but get " + actual, 80, "");
144 _buffer = _helper.Unwrap (rawBuffer, 0, length);
145 _bufferPosition = 0;
146 return _buffer.Length;
149 private int ReadAll(byte [] buffer, int total)
151 int count = 0;
152 int pos = 0;
153 while (total > 0) {
154 count = _stream.Read (buffer, pos, total);
156 if (count == -1)
157 break;
158 //return ((pos == 0) ? -1 : pos);
160 pos += count;
161 total -= count;
163 return pos;
166 public override long Seek(long offset, SeekOrigin loc)
168 return _stream.Seek (offset, loc);
171 public override void SetLength(long value)
173 _stream.SetLength (value);
176 public override void Write(byte [] buffer, int offset, int count)
178 // FIXME: use GSSCOntext.getWrapSizeLimit to divide the buffer
179 // Generate wrapped token
180 byte [] wrappedToken = _helper.Wrap (buffer, offset, count);
181 // Write out length
182 IntToNetworkByteOrder (wrappedToken.Length, _lenBuf, 0, 4);
183 _stream.Write (_lenBuf, 0, 4);
184 // Write out wrapped token
185 _stream.Write (wrappedToken, 0, wrappedToken.Length);
188 internal static int NetworkByteOrderToInt(byte [] buf, int start, int count)
190 int answer = 0;
191 for (int i = 0; i < count; i++) {
192 answer <<= 8;
193 answer |= ((int)buf [start + i] & 0xff);
195 return answer;
198 internal static void IntToNetworkByteOrder(int num, byte [] buf, int start, int count)
200 for (int i = count-1; i >= 0; i--) {
201 buf [start + i] = (byte)(num & 0xff);
202 num >>= 8;
206 #endregion // Methods