2 // Novell.Directory.Ldap.Security.SecureStream.cs
5 // Boris Kirzner <borsk@mainsoft.com>
6 // Konstantin Triger <kostat@mainsoft.com>
8 // (C) 2005 Mainsoft Corporation (http://www.mainsoft.com)
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:
20 // The above copyright notice and this permission notice shall be
21 // included in all copies or substantial portions of the Software.
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.
35 namespace Novell
.Directory
.Ldap
.Security
37 internal class SecureStream
: Stream
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
;
52 public SecureStream(Stream stream
, Krb5Helper helper
): base ()
58 #endregion // Constructors
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
92 public override void Flush()
97 public override int Read( byte [] buffer
, int offset
, int count
)
99 if (_buffer
== null || _bufferPosition
>= _buffer
.Length
) {
100 int actual
= Fill ();
108 int available
= _buffer
.Length
- _bufferPosition
;
109 if (count
> available
) {
110 Array
.Copy (_buffer
, _bufferPosition
, buffer
, offset
, available
);
111 _bufferPosition
= _buffer
.Length
;
115 Array
.Copy (_buffer
, _bufferPosition
, buffer
, offset
, count
);
116 _bufferPosition
+= count
;
121 public override void Close() {
128 int actual
= ReadAll (_lenBuf
, 4);
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
);
146 return _buffer
.Length
;
149 private int ReadAll(byte [] buffer
, int total
)
154 count
= _stream
.Read (buffer
, pos
, total
);
158 //return ((pos == 0) ? -1 : 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
);
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
)
191 for (int i
= 0; i
< count
; i
++) {
193 answer
|= ((int)buf
[start
+ i
] & 0xff);
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);
206 #endregion // Methods